Java tutorial
/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (C) Alkacon Software (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * For further information about Alkacon Software, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.jlan; import org.opencms.file.CmsResource; import org.opencms.file.CmsResourceFilter; import org.opencms.file.CmsVfsResourceAlreadyExistsException; import org.opencms.file.CmsVfsResourceNotFoundException; import org.opencms.file.wrapper.CmsObjectWrapper; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.main.OpenCms; import org.opencms.security.CmsSecurityException; import org.opencms.util.CmsStringUtil; import org.opencms.util.I_CmsRegexSubstitution; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.alfresco.jlan.server.SrvSession; import org.alfresco.jlan.server.core.DeviceContext; import org.alfresco.jlan.server.filesys.AccessDeniedException; import org.alfresco.jlan.server.filesys.DiskInterface; import org.alfresco.jlan.server.filesys.FileExistsException; import org.alfresco.jlan.server.filesys.FileInfo; import org.alfresco.jlan.server.filesys.FileOpenParams; import org.alfresco.jlan.server.filesys.FileStatus; import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.SearchContext; import org.alfresco.jlan.server.filesys.TreeConnection; import org.alfresco.jlan.util.WildCard; import org.springframework.extensions.config.ConfigElement; import com.google.common.base.Joiner; /** * OpenCms implementation of the JLAN DiskInterface interface.<p> * * This class, together with the CmsJlanNetworkFile class, contains the main repository access functionality.<p> */ public class CmsJlanDiskInterface implements DiskInterface { /** Attribute to control whether we need the filesize or not when reading a resource. */ public static final String NO_FILESIZE_REQUIRED = "NO_FILESIZE_REQUIRED"; /** The standard resource filter used for reading resources. */ public static final CmsResourceFilter STANDARD_FILTER = CmsResourceFilter.ONLY_VISIBLE_NO_DELETED; /** The logger instance for this class. */ private static final Log LOG = CmsLog.getLog(CmsJlanDiskInterface.class); /** * Tries to convert a CmsException to the matching exception type from JLAN.<p> * * @param e the exception to convert * @return the converted exception */ public static IOException convertCmsException(CmsException e) { LOG.error(e.getLocalizedMessage(), e); if (e instanceof CmsSecurityException) { return new AccessDeniedException(e.getMessage(), e); } else if (e instanceof CmsVfsResourceAlreadyExistsException) { return new FileExistsException("File exists: " + e); } else if (e instanceof CmsVfsResourceNotFoundException) { return new FileNotFoundException("File does not exist: " + e); } else { return new IOException(e); } } /** * Converts a CIFS path to an OpenCms path by converting backslashes to slashes and translating special characters in the file name.<p> * * @param path the path to transform * @return the OpenCms path for the given path */ protected static String getCmsPath(String path) { String slashPath = path.replace('\\', '/'); // split path into components, translate each of them separately, then combine them again at the end String[] segments = slashPath.split("/"); List<String> nonEmptySegments = new ArrayList<String>(); for (String segment : segments) { if (segment.length() > 0) { String translatedSegment = "*".equals(segment) ? "*" : OpenCms.getResourceManager().getFileTranslator().translateResource(segment); nonEmptySegments.add(translatedSegment); } } String result = "/" + Joiner.on("/").join(nonEmptySegments); return result; } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#closeFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.NetworkFile) */ public void closeFile(SrvSession session, TreeConnection connection, NetworkFile file) throws IOException { file.close(); } /** * @see org.alfresco.jlan.server.core.DeviceInterface#createContext(java.lang.String, org.springframework.extensions.config.ConfigElement) */ public DeviceContext createContext(String shareName, ConfigElement args) { return null; // not used, since the repository creates the device context } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#createDirectory(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.FileOpenParams) */ public void createDirectory(SrvSession session, TreeConnection connection, FileOpenParams params) throws IOException { internalCreateFile(session, connection, params, "folder"); } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#createFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.FileOpenParams) */ public NetworkFile createFile(SrvSession session, TreeConnection connection, FileOpenParams params) throws IOException { return internalCreateFile(session, connection, params, null); } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#deleteDirectory(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, java.lang.String) */ public void deleteDirectory(SrvSession session, TreeConnection connection, String path) throws IOException { deleteFile(session, connection, path); } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#deleteFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, java.lang.String) */ public void deleteFile(SrvSession session, TreeConnection connection, String path) throws IOException { // note: deletion of a file may not necessarily go through this method, instead the client program may open the // file, set a "delete on close" flag, and then close it. try { CmsJlanNetworkFile file = getFileForPath(session, connection, path); if (file == null) { // Only log a warning, since if the file doesn't exist, it doesn't really need to be deleted anymore LOG.warn("Couldn't delete file " + path + " because it doesn't exist anymore."); } else { file.delete(); } } catch (CmsException e) { throw convertCmsException(e); } } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#fileExists(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, java.lang.String) */ public int fileExists(SrvSession session, TreeConnection connection, String path) { try { CmsObjectWrapper cms = getCms(session, connection); cms.getRequestContext().setAttribute(NO_FILESIZE_REQUIRED, Boolean.TRUE); CmsJlanNetworkFile file = getFileForPath(cms, session, connection, path); if (file == null) { return FileStatus.NotExist; } else { return file.isDirectory() ? FileStatus.DirectoryExists : FileStatus.FileExists; } } catch (Exception e) { System.out.println(e); return FileStatus.NotExist; } } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#flushFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.NetworkFile) */ public void flushFile(SrvSession session, TreeConnection connection, NetworkFile file) throws IOException { file.flushFile(); } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#getFileInformation(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, java.lang.String) */ public FileInfo getFileInformation(SrvSession session, TreeConnection connection, String path) throws IOException { try { if (path == null) { throw new FileNotFoundException("file not found: " + path); } CmsJlanNetworkFile file = getFileForPath(session, connection, path); if (file == null) { return null; //throw new FileNotFoundException("path not found: " + path); } else { return file.getFileInfo(); } } catch (CmsException e) { throw convertCmsException(e); } } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#isReadOnly(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.core.DeviceContext) */ public boolean isReadOnly(SrvSession session, DeviceContext context) { return false; } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#openFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.FileOpenParams) */ public NetworkFile openFile(SrvSession session, TreeConnection connection, FileOpenParams params) throws IOException { String path = params.getPath(); String cmsPath = getCmsPath(path); // TODO: Check access control try { CmsObjectWrapper cms = getCms(session, connection); CmsResource resource = cms.readResource(cmsPath, STANDARD_FILTER); return new CmsJlanNetworkFile(cms, resource, path); } catch (CmsException e) { throw convertCmsException(e); } } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#readFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.NetworkFile, byte[], int, int, long) */ public int readFile(SrvSession sess, TreeConnection tree, NetworkFile file, byte[] buf, int bufPos, int siz, long filePos) throws java.io.IOException { // Check if the file is a directory if (file.isDirectory()) { throw new AccessDeniedException(); } // Read the file int rdlen = file.readFile(buf, siz, bufPos, filePos); // If we have reached end of file return a zero length read if (rdlen < 0) { rdlen = 0; } // Return the actual read length return rdlen; } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#renameFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, java.lang.String, java.lang.String) */ public void renameFile(SrvSession session, TreeConnection connection, String oldName, String newName) throws IOException { String cmsNewPath = getCmsPath(newName); try { CmsJlanNetworkFile file = getFileForPath(session, connection, oldName); file.moveTo(cmsNewPath); } catch (CmsException e) { throw convertCmsException(e); } } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#seekFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.NetworkFile, long, int) */ public long seekFile(SrvSession session, TreeConnection connection, NetworkFile file, long pos, int seekMode) throws IOException { return file.seekFile(pos, seekMode); } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#setFileInformation(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, java.lang.String, org.alfresco.jlan.server.filesys.FileInfo) */ public void setFileInformation(SrvSession session, TreeConnection connection, String path, FileInfo info) throws IOException { try { CmsObjectWrapper cms = getCms(session, connection); String cmsPath = getCmsPath(path); CmsResource resource = cms.readResource(cmsPath, STANDARD_FILTER); CmsJlanNetworkFile file = new CmsJlanNetworkFile(cms, resource, path); file.setFileInformation(info); } catch (CmsException e) { throw convertCmsException(e); } } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#startSearch(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, java.lang.String, int) */ public SearchContext startSearch(SrvSession session, TreeConnection connection, String searchPath, int searchAttributes) { try { String cmsPath = getCmsPath(searchPath); if (cmsPath.endsWith("/")) { cmsPath = cmsPath + "*"; } String name = CmsResource.getName(cmsPath); String parent = CmsResource.getParentFolder(cmsPath); if (WildCard.containsWildcards(name)) { CmsJlanNetworkFile parentFile = getFileForPath(session, connection, parent); return new CmsJlanSearch(parentFile.search(name, searchAttributes)); } else { CmsJlanNetworkFile file = getFileForPath(session, connection, cmsPath); return new CmsJlanSearch(Collections.singletonList(file)); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @see org.alfresco.jlan.server.core.DeviceInterface#treeClosed(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection) */ public void treeClosed(SrvSession sess, TreeConnection tree) { // ignore } /** * @see org.alfresco.jlan.server.core.DeviceInterface#treeOpened(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection) */ public void treeOpened(SrvSession arg0, TreeConnection arg1) { // ignore } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#truncateFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.NetworkFile, long) */ public void truncateFile(SrvSession session, TreeConnection connection, NetworkFile file, long size) throws IOException { file.truncateFile(size); } /** * @see org.alfresco.jlan.server.filesys.DiskInterface#writeFile(org.alfresco.jlan.server.SrvSession, org.alfresco.jlan.server.filesys.TreeConnection, org.alfresco.jlan.server.filesys.NetworkFile, byte[], int, int, long) */ public int writeFile(SrvSession session, TreeConnection connection, NetworkFile file, byte[] data, int bufferOffset, int length, long fileOffset) throws IOException { if (file.isDirectory()) { throw new AccessDeniedException("Can't write data to a directory!"); } file.writeFile(data, length, bufferOffset, fileOffset); return length; } /** * Creates a CmsObjectWrapper for the current session.<p> * * @param session the current session * @param connection the tree connection * * @return the correctly configured CmsObjectWrapper for this session * * @throws CmsException if something goes wrong */ protected CmsObjectWrapper getCms(SrvSession session, TreeConnection connection) throws CmsException { CmsJlanRepository repository = ((CmsJlanDeviceContext) connection.getContext()).getRepository(); CmsObjectWrapper result = repository.getCms(session, connection); return result; } /** * Helper method to get a network file object given a path.<p> * * @param cms the CMS context wrapper * @param session the current session * @param connection the current connection * @param path the file path * * @return the network file object for the given path * @throws CmsException if something goes wrong */ protected CmsJlanNetworkFile getFileForPath(CmsObjectWrapper cms, SrvSession session, TreeConnection connection, String path) throws CmsException { try { String cmsPath = getCmsPath(path); CmsResource resource = cms.readResource(cmsPath, STANDARD_FILTER); CmsJlanNetworkFile result = new CmsJlanNetworkFile(cms, resource, path); return result; } catch (CmsVfsResourceNotFoundException e) { return null; } } /** * Helper method to get a network file object given a path.<p> * * @param session the current session * @param connection the current connection * @param path the file path * * @return the network file object for the given path * @throws CmsException if something goes wrong */ protected CmsJlanNetworkFile getFileForPath(SrvSession session, TreeConnection connection, String path) throws CmsException { CmsObjectWrapper cms = getCms(session, connection); return getFileForPath(cms, session, connection, path); } /** * Internal method for creating a new file.<p> * * @param session the session * @param connection the tree connection * @param params the parameters for opening the file * @param typeName the name of the resource type for the new file * * @return a NetworkFile instance representing the newly created file * * @throws IOException if something goes wrong */ protected NetworkFile internalCreateFile(SrvSession session, TreeConnection connection, FileOpenParams params, String typeName) throws IOException { String path = params.getPath(); String cmsPath = getCmsPath(path); try { CmsObjectWrapper cms = getCms(session, connection); if (typeName == null) { typeName = OpenCms.getResourceManager().getDefaultTypeForName(cmsPath).getTypeName(); } CmsResource createdResource = cms.createResource(cmsPath, OpenCms.getResourceManager().getResourceType(typeName).getTypeId()); tryUnlock(cms, cmsPath); CmsJlanNetworkFile result = new CmsJlanNetworkFile(cms, createdResource, path); result.setFullName(params.getPath()); return result; } catch (CmsVfsResourceAlreadyExistsException e) { throw new FileExistsException("File exists: " + path); } catch (CmsException e) { throw new IOException(e); } } /** * Translates the last path segment of a path using the configured OpenCms file translations.<p> * * @param path the path for which the last segment should be translated * * @return the path with the translated last segment */ protected String translateName(String path) { return CmsStringUtil.substitute(Pattern.compile("/([^/]+)$"), path, new I_CmsRegexSubstitution() { public String substituteMatch(String text, Matcher matcher) { String name = text.substring(matcher.start(1), matcher.end(1)); return "/" + OpenCms.getResourceManager().getFileTranslator().translateResource(name); } }); } /** * Tries to unlock the file at the given path.<p> * * @param cms the CMS context wrapper * @param path the path of the resource to unlock */ private void tryUnlock(CmsObjectWrapper cms, String path) { try { cms.unlockResource(path); } catch (Throwable e) { LOG.info(e.getLocalizedMessage(), e); } } }