components/visual-panels/core/src/java/vpanels/client/com/oracle/solaris/vp/client/common/PanelResourceManager.java
changeset 827 0944d8c0158b
child 1410 ca9946e5736c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/visual-panels/core/src/java/vpanels/client/com/oracle/solaris/vp/client/common/PanelResourceManager.java	Thu May 24 04:16:47 2012 -0400
@@ -0,0 +1,245 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+
+package com.oracle.solaris.vp.client.common;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.util.*;
+import com.oracle.solaris.rad.jmx.IncompatibleVersionException;
+import com.oracle.solaris.vp.panel.common.*;
+import com.oracle.solaris.vp.panel.common.action.ActionAbortedException;
+import com.oracle.solaris.vp.panel.common.api.panel.*;
+import com.oracle.solaris.vp.util.misc.*;
+import com.oracle.solaris.vp.util.misc.finder.Finder;
+
+public abstract class PanelResourceManager {
+    //
+    // PanelResourceManager methods
+    //
+
+    /**
+     * Returns the PanelResourceManager subclass -determined user
+     * directory.
+     */
+    abstract protected String getUserDir();
+
+    /**
+     * Checks to see if the download process has been cancelled.  Subclasses
+     * should override this method if they provide a method for the user to
+     * cancel the login process.  This default implementation does nothing.
+     *
+     * @exception   ActionAbortedException
+     *		    if the action has been cancelled
+     */
+    protected void checkForCancel() throws ActionAbortedException {
+    }
+
+    /**
+     * Downloads all resources needed by a particular {@link CustomPanel}.
+     *
+     * @param	    info
+     *		    the connection information
+     *
+     * @param	    panel
+     *		    the {@link CustomPanel} that requires resources downloaded
+     *
+     * @return	    the {@code URL}s pointing to local copies of the downloaded
+     *		    resources for the given panel, or {@code null} if an error
+     *		    occurred
+     *
+     * @exception   ActionAbortedException
+     *		    if the download is aborted before it is complete
+     *
+     * @exception   PanelResourceException
+     *		    if a resource could not be downloaded
+     */
+    protected URL[] downloadAll(ConnectionInfo info, CustomPanel panel)
+	throws ActionAbortedException, PanelResourceException
+    {
+	List<URL> urls = new ArrayList<URL>();
+	boolean isLocal = NetUtil.isLocalAddress(info.getHost());
+
+	PanelMXBeanTracker tracker = null;
+	PanelMXBean bean = null;
+
+	// Download each resource
+	for (ResourceDescriptor descriptor : panel.getResourceDescriptors()) {
+	    checkForCancel();
+
+	    InputStream in = null;
+	    String fileName = null;
+	    String remoteFile = descriptor.getFile();
+
+	    try {
+		fileName = isLocal ? remoteFile :
+		    getLocalCacheName(info, remoteFile);
+
+		final File file = new File(fileName);
+		URI uri = AccessController.doPrivileged(
+		    new PrivilegedAction<URI>() {
+			@Override
+			public URI run() {
+			    return file.toURI();
+			}
+		    });
+		urls.add(uri.toURL());
+
+		if (!isLocal) {
+		    boolean download = true;
+
+		    if (file.exists()) {
+			byte[] sHash = descriptor.getHash();
+			if (sHash != null) {
+			    byte[] cHash = FileUtil.getHash(
+				fileName, descriptor.getHashAlgorithm());
+
+			    if (Arrays.equals(sHash, cHash)) {
+				download = false;
+			    }
+			}
+		    }
+
+		    if (download) {
+			final File parent = file.getParentFile();
+			if (parent != null && !parent.exists()) {
+			    String path = parent.getCanonicalPath();
+			    showStatus(Finder.getString("download.status.mkdir",
+				path));
+
+			    if (!AccessController.doPrivileged(
+				new PrivilegedAction<Boolean>() {
+				    @Override
+				    public Boolean run() {
+					return parent.mkdirs();
+				    }
+				})) {
+				throw new IOException(
+				    Finder.getString("download.error.mkdir",
+				    path));
+			    }
+
+			    checkForCancel();
+			}
+
+			showStatus(Finder.getString(
+			    "download.status.download", fileName));
+
+			if (bean == null) {
+			    if (tracker == null) {
+				tracker = createTracker(info);
+			    }
+			    bean = tracker.getBean();
+			}
+
+			final byte[] resource = bean.getResource(
+			    descriptor.getToken());
+
+			AccessController.doPrivileged(
+			    new PrivilegedExceptionAction<Object>() {
+				@Override
+				public Object run() throws IOException {
+				    OutputStream out =
+					new FileOutputStream(file);
+				    out.write(resource);
+				    out.close();
+				    return null;
+				}
+			    });
+		    }
+		}
+	    }
+
+	    catch (Exception e) {
+		throw new PanelResourceException(Finder.getString(
+		    "download.error.download", panel.getName(), info.getHost(),
+		    remoteFile), e);
+	    }
+
+	    finally  {
+		IOUtil.closeIgnore(in);
+		if (tracker != null) {
+		    tracker.dispose();
+		}
+	    }
+	}
+
+	return urls.toArray(new URL[urls.size()]);
+    }
+
+    /**
+     * Returns the file name of the locally cached version of the given remote
+     * file, mapped to {@link PanelResourceManager#getUserDir
+     * userdir}/cache/<i>host</i>/<i>path</i>.
+     */
+    public String getLocalCacheName(ConnectionInfo info, String remoteFile) {
+	return TextUtil.join(File.separator,
+	    getUserDir(), "cache", info.getHost(), remoteFile);
+    }
+
+    /**
+     * Displays the user-friendly status of this {@code PanelResourceManager}.
+     * Subclasses may wish to override this method -- this default
+     * implementation does nothing.
+     */
+    protected void showStatus(String status) {
+    }
+
+    //
+    // Private methods
+    //
+
+    private PanelMXBeanTracker createTracker(ConnectionInfo info)
+	throws PanelResourceException {
+
+	PanelMXBeanTracker tracker;
+
+	try {
+	    tracker = new PanelMXBeanTracker();
+	    tracker.setConnectionInfo(info);
+
+	} catch (TrackerException e) {
+	    Throwable cause = e.getCause();
+	    String message;
+
+	    if (cause instanceof IncompatibleVersionException) {
+		IncompatibleVersionException ive =
+		    (IncompatibleVersionException)cause;
+
+		message = Finder.getString("proxy.error.version",
+		    ive.getClientVersion(), ive.getServerVersion(),
+		    ive.getInterfaceClass().getSimpleName());
+	    } else {
+		message = Finder.getString("download.error.general",
+		    info.getHost());
+	    }
+
+	    throw new PanelResourceException(message, cause);
+	}
+
+	return tracker;
+    }
+}