?? expandingarchiveclasspathentry.java
字號:
} // if the content root is not set, unpack and save if (jarRoot == null) { jarRoot = jarNode.addNode(NODE_JARCONTENTS, "nt:folder"); unpack(jarRoot); jarNode.save(); } } finally { // rollback changes on the jar node in case of problems if (jarNode != null && jarNode.isModified()) { // rollback incomplete modifications log.warn("Rolling back unsaved changes on JAR node {}", getPath()); try { jarNode.refresh(false); } catch (RepositoryException re) { log.warn("Cannot rollback changes after failure to " + "expand " + getPath(), re); } } } jarContents = jarRoot; } return jarContents; } /** * Expands the archive stored in the property of this class path entry into * the repositroy below the given <code>jarRoot</code> node. * <p> * This method leaves the subtree at and below <code>jarRoot</code> unsaved. * It is the task of the caller to save or rollback as appropriate. * * @param jarRoot The <code>Node</code> below which the archive is to be * unpacked. * * @throws RepositoryException If an error occurrs creating the item * structure to unpack the archive or if an error occurrs reading * the archive. */ private void unpack(Node jarRoot) throws RepositoryException { ZipInputStream zin = null; try { zin = new ZipInputStream(getProperty().getStream()); ZipEntry entry = zin.getNextEntry(); while (entry != null) { if (entry.isDirectory()) { unpackFolder(jarRoot, entry.getName()); } else { unpackFile(jarRoot, entry, zin); } entry = zin.getNextEntry(); } } catch (IOException ioe) { throw new RepositoryException( "Problem reading JAR contents of " + getPath(), ioe); } finally { // close the JAR stream if open if (zin != null) { try { zin.close(); } catch (IOException ignore) {} } } } /** * Makes sure a node exists at the <code>path</code> relative to * <code>root</code>. In other words, this method returns the node * <code>root.getNode(path)</code>, creating child nodes as required. Newly * created nodes are created with node type <code>nt:folder</code>. * <p> * If intermediate nodes or the actual node required already exist, they * must be typed such, that they may either accept child node creations * of type <code>nt:file</code> or <code>nt:folder</code>. * * @param root The <code>Node</code> relative to which a node representing * a folder is to created if required. * @param path The path relative to <code>root</code> of the folder to * ensure. * * @return The <code>Node</code> representing the folder below * <code>root</code>. * * @throws RepositoryException If an error occurrs accessing the repository * or creating missing node(s). */ private Node unpackFolder(Node root, String path) throws RepositoryException { // remove trailing slash while (path.endsWith("/")) { path = path.substring(0, path.length()-1); } // quick check if the folder already exists if (root.hasNode(path)) { return root.getNode(path); } // go down and create the path StringTokenizer tokener = new StringTokenizer(path, "/"); while (tokener.hasMoreTokens()) { String label = tokener.nextToken(); if (root.hasNode(label)) { root = root.getNode(label); } else { root = root.addNode(label, "nt:folder"); } } // return the final node return root; } /** * Creates a <code>nt:file</code> node with the path * <code>entry.getName()</code> relative to the <code>root</code> node. The * contents of the <code>jcr:content/jcr:data</code> property of the file * node is retrieved from <code>ins</code>. * <p> * The <code>jcr:content/jcr:lastModified</code> property is set to the * value of the <code>time</code> field of the <code>entry</code>. The * <code>jcr:content/jcr:mimeType</code> property is set to a best-effort * guess of the content type of the entry. To guess the content type, the * <code>java.net.URLConnection.guessContentType(String)</code> method * is called. If this results in no content type, the default * <code>application/octet-stream</code> is set. * * @param root The node relative to which the <code>nt:file</code> node * is created. * @param entry The <code>ZipEntry</code> providing information on the * file to be created. Namely the <code>name</code> and * <code>time</code> fields are used. * @param ins The <code>InputStream</code> providing the data to be written * to the <code>jcr:content/jcr:data</code> property. * * @throws RepositoryException If an error occurrs creating and filling * the <code>nt:file</code> node. */ private void unpackFile(Node root, ZipEntry entry, InputStream ins) throws RepositoryException { int slash = entry.getName().lastIndexOf('/'); String label = entry.getName().substring(slash+1); Node parent = (slash <= 0) ? root : unpackFolder(root, entry.getName().substring(0, slash)); // remove existing node (and all children by the way !!) if (parent.hasNode(label)) { parent.getNode(label).remove(); } // prepare property values Calendar lastModified = Calendar.getInstance(); lastModified.setTimeInMillis(entry.getTime()); String mimeType = URLConnection.guessContentTypeFromName(label); if (mimeType == null) { mimeType = "application/octet-stream"; } // create entry nodes Node ntFile = parent.addNode(label, "nt:file"); Node content = ntFile.addNode("jcr:content", "nt:resource"); content.setProperty("jcr:mimeType", mimeType); content.setProperty("jcr:data", ins); content.setProperty("jcr:lastModified", lastModified); } /** * Checks whether it is possible to use this class for archive class path * entries in the workspace (and repository) to which the <code>session</code> * provides access. * <p> * This method works as follows. If the node type <code>rep:jarFile</code> * is defined in the session's repository, <code>true</code> is immediately * returned. If an error checking for the node type, <code>false</code> is * immediately returned. * <p> * If the node type is not defined, the * {@link NodeTypeSupport#registerNodeType(Workspace)} method is called * to register the node type. Any errors occurring while calling or * executing this method is logged an <code>false</code> is returned. * Otherwise, if node type registration succeeded, <code>true</code> is * returned. * <p> * This method is synchronized such that two paralell threads do not try * to create the node, which might yield wrong negatives. * * @param session The <code>Session</code> providing access to the * repository. * * @return <code>true</code> if this class can be used to handle archive * class path entries. See above for a description of the test used. */ /* package */ synchronized static boolean canExpandArchives(Session session) { // quick check for the node type, succeed if defined try { session.getWorkspace().getNodeTypeManager().getNodeType(TYPE_JARFILE); log.debug("Required node type exists, can expand archives"); return true; } catch (NoSuchNodeTypeException nst) { log.debug("Required node types does not exist, try to define"); } catch (RepositoryException re) { log.info("Cannot check for required node type, cannot expand " + "archives", re); return false; } try { Workspace workspace = session.getWorkspace(); return NodeTypeSupport.registerNodeType(workspace); } catch (Throwable t) { // Prevent anything from hapening if node type registration fails // due to missing libraries or other errors log.info("Error registering node type", t); } // fallback to failure return false; }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -