/******************************************************************************* * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * 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. * *******************************************************************************/ package com.liferay.ide.project.core; import com.liferay.ide.core.ILiferayConstants; import com.liferay.ide.core.IWebProject; import com.liferay.ide.core.LiferayCore; import com.liferay.ide.core.util.CoreUtil; import com.liferay.ide.core.util.StringPool; import com.liferay.ide.project.core.util.ProjectUtil; import com.liferay.ide.sdk.core.ISDKConstants; import com.liferay.ide.sdk.core.SDK; import com.liferay.ide.sdk.core.SDKUtil; import com.liferay.ide.server.core.LiferayServerCore; import com.liferay.ide.server.util.ComponentUtil; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Properties; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IAccessRule; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jst.common.jdt.internal.classpath.ClasspathDecorations; import org.eclipse.jst.common.jdt.internal.classpath.ClasspathDecorationsManager; import org.eclipse.wst.common.componentcore.ComponentCore; import org.eclipse.wst.common.componentcore.resources.IVirtualComponent; /** * @author Greg Amerson */ @SuppressWarnings( "restriction" ) public abstract class PluginClasspathContainer implements IClasspathContainer { protected static final Collection<String> portalSourceJars = Arrays.asList ( "util-bridges.jar", //$NON-NLS-1$ "util-java.jar", //$NON-NLS-1$ "util-taglib.jar", //$NON-NLS-1$ "portal-impl.jar" //$NON-NLS-1$ ); protected static ClasspathDecorationsManager cpDecorations; protected static final String SEPARATOR = "!"; //$NON-NLS-1$ static { cpDecorations = new ClasspathDecorationsManager( LiferayServerCore.PLUGIN_ID ); } public static String getDecorationManagerKey( IProject project, String container ) { return project.getName() + SEPARATOR + container; } static ClasspathDecorationsManager getDecorationsManager() { return cpDecorations; } protected IClasspathEntry[] classpathEntries; protected IJavaProject javaProject; protected IPath path; protected IPath pluginPackageFilePath; protected IPath portalDir; protected String javadocURL; protected IPath sourceLocation; public PluginClasspathContainer( IPath containerPath, IJavaProject project, IPath portalDir, String javadocURL, IPath sourceURL ) { this.path = containerPath; this.javaProject = project; this.portalDir = portalDir; this.javadocURL = javadocURL; this.sourceLocation = sourceURL; } public IClasspathEntry[] getClasspathEntries() { if( this.classpathEntries == null ) { List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>(); if( this.portalDir != null ) { for( String pluginJar : getPortalJars() ) { entries.add( createPortalJarClasspathEntry( pluginJar ) ); } for( String pluginPackageJar : getPortalDependencyJars() ) { entries.add( createPortalJarClasspathEntry( pluginPackageJar ) ); } } this.classpathEntries = entries.toArray( new IClasspathEntry[entries.size()] ); } return this.classpathEntries; } public abstract String getDescription(); public int getKind() { return K_APPLICATION; } public IPath getPath() { return this.path; } public IPath getPortalDir() { return portalDir; } public String getJavadocURL() { return javadocURL; } public IPath getSourceLocation() { return sourceLocation; } protected IClasspathEntry createClasspathEntry( IPath entryPath, IPath sourcePath ) { return createClasspathEntry( entryPath, sourcePath, null ); } protected IClasspathEntry createClasspathEntry( IPath entryPath, IPath sourceLocation, String javadocURL ) { IPath sourceRootPath = null; IPath sourcePath = null; IAccessRule[] rules = new IAccessRule[] {}; IClasspathAttribute[] attrs = new IClasspathAttribute[] {}; final ClasspathDecorations dec = cpDecorations.getDecorations( getDecorationManagerKey( javaProject.getProject(), getPath().toString() ), entryPath.toString() ); if( dec != null ) { sourcePath = dec.getSourceAttachmentPath(); sourceRootPath = dec.getSourceAttachmentRootPath(); attrs = dec.getExtraAttributes(); } if( javadocURL != null ) { if( CoreUtil.empty( attrs ) ) { attrs = new IClasspathAttribute[] { newJavadocAttr( javadocURL ) }; } else { List<IClasspathAttribute> newAttrs = new ArrayList<IClasspathAttribute>(); for( IClasspathAttribute attr : attrs ) { if( IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals( attr.getName() ) ) { newAttrs.add( newJavadocAttr( javadocURL ) ); } else { newAttrs.add( attr ); } } attrs = newAttrs.toArray( new IClasspathAttribute[0] ); } } if( sourcePath == null && sourceLocation != null ) { sourcePath = sourceLocation; } return JavaCore.newLibraryEntry( entryPath, sourcePath, sourceRootPath, rules, attrs, false ); } protected IClasspathAttribute newJavadocAttr( String javadocURL ) { return JavaCore.newClasspathAttribute( IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME, javadocURL ); } protected IClasspathEntry createContextClasspathEntry( String context ) { IClasspathEntry entry = null; IFile serviceJar = ComponentUtil.findServiceJarForContext( context ); if( serviceJar.exists() ) { final IWebProject webproject = LiferayCore.create( IWebProject.class, serviceJar.getProject() ); // IDE-110 IDE-648 if( webproject != null && webproject.getDefaultDocrootFolder() != null ) { IFolder defaultDocroot = webproject.getDefaultDocrootFolder(); IFolder serviceFolder = defaultDocroot.getFolder( new Path( "WEB-INF/service") ); //$NON-NLS-1$ if( serviceFolder.exists() ) { entry = createClasspathEntry( serviceJar.getLocation(), serviceFolder.getLocation() ); } } if( entry == null ) { entry = createClasspathEntry( serviceJar.getLocation(), null ); } } //TODO IDE-657 IDE-110 if( entry == null ) { IProject project = this.javaProject.getProject(); SDK sdk = SDKUtil.getSDK( project ); IPath sdkLocation = sdk.getLocation(); String type = ProjectUtil.isPortletProject( project ) ? "portlets" : ProjectUtil.isHookProject( project ) //$NON-NLS-1$ ? "hooks" : ProjectUtil.isExtProject( project ) ? "ext" : StringPool.EMPTY; //$NON-NLS-1$ //$NON-NLS-2$ IPath serviceJarPath = sdkLocation.append( type ).append( context ).append( ISDKConstants.DEFAULT_DOCROOT_FOLDER + "/WEB-INF/lib" ).append( context + "-service.jar" ); //$NON-NLS-1$ //$NON-NLS-2$ if( serviceJarPath.toFile().exists() ) { IPath servicePath = serviceJarPath.removeLastSegments( 2 ).append( "service" ); //$NON-NLS-1$ entry = createClasspathEntry( serviceJarPath, servicePath.toFile().exists() ? servicePath : null ); } } return entry; } protected IClasspathEntry createPortalJarClasspathEntry( String portalJar ) { IPath entryPath = this.portalDir.append( "/WEB-INF/lib/" + portalJar ); //$NON-NLS-1$ IPath sourcePath = null; if( portalSourceJars.contains( portalJar ) ) { sourcePath = getSourceLocation(); } return createClasspathEntry( entryPath, sourcePath, this.javadocURL ); } protected IClasspathEntry findSuggestedEntry( IPath jarPath, IClasspathEntry[] suggestedEntries ) { // compare jarPath to an existing entry if( jarPath != null && ( !CoreUtil.isNullOrEmpty( jarPath.toString() ) ) && ( !CoreUtil.isNullOrEmpty( suggestedEntries ) ) ) { int matchLength = jarPath.segmentCount(); for( IClasspathEntry suggestedEntry : suggestedEntries ) { IPath suggestedPath = suggestedEntry.getPath(); IPath pathToMatch = suggestedPath.removeFirstSegments( suggestedPath.segmentCount() - matchLength ).setDevice( null ).makeAbsolute(); if( jarPath.equals( pathToMatch ) ) { return suggestedEntry; } } } return null; } protected IFile getPluginPackageFile() { IFile retval = null; if( pluginPackageFilePath == null ) { retval = lookupPluginPackageFile(); if( retval != null && retval.exists() ) { pluginPackageFilePath = retval.getFullPath(); return retval; } } else { retval = ResourcesPlugin.getWorkspace().getRoot().getFile( pluginPackageFilePath ); if( !retval.exists() ) { pluginPackageFilePath = null; retval = lookupPluginPackageFile(); } } return retval; } protected String[] getPortalDependencyJars() { String[] jars = new String[0]; IFile pluginPackageFile = getPluginPackageFile(); try { String deps = getPropertyValue( "portal-dependency-jars", pluginPackageFile ); //$NON-NLS-1$ String[] split = deps.split( StringPool.COMMA ); if( split.length > 0 && !( CoreUtil.isNullOrEmpty( split[0] ) ) ) { for( int i = 0; i < split.length; i++ ) { split[i] = split[i].trim(); } return split; } } catch( Exception e ) { } return jars; } protected abstract String[] getPortalJars(); protected String getPropertyValue( String key, IFile propertiesFile ) { String retval = null; InputStream contents = null; try { Properties props = new Properties(); contents = getPluginPackageFile().getContents(); props.load( contents ); retval = props.getProperty( key, StringPool.EMPTY ); } catch( Exception e ) { } finally { if( contents != null ) { try { contents.close(); } catch( Exception e ) { // best effort } } } return retval; } protected String[] getRequiredDeploymentContexts() { String[] jars = new String[0]; IFile pluginPackageFile = getPluginPackageFile(); try { String context = getPropertyValue( "required-deployment-contexts", pluginPackageFile ); //$NON-NLS-1$ String[] split = context.split( StringPool.COMMA ); if( split.length > 0 && !( CoreUtil.isNullOrEmpty( split[0] ) ) ) { return split; } } catch( Exception e ) { } return jars; } protected IFile lookupPluginPackageFile() { IFile pluginPackageFile = null; IVirtualComponent comp = ComponentCore.createComponent( this.javaProject.getProject() ); if( comp != null ) { IContainer resource = comp.getRootFolder().getUnderlyingFolder(); if( resource instanceof IFolder ) { IFolder webroot = (IFolder) resource; pluginPackageFile = webroot.getFile( "WEB-INF/" + ILiferayConstants.LIFERAY_PLUGIN_PACKAGE_PROPERTIES_FILE ); //$NON-NLS-1$ if( !pluginPackageFile.exists() ) { // IDE-226 the file may be missing because we are in an ext plugin which has a different layout // check for ext-web in the path to the docroot if( webroot.getFullPath().toPortableString().endsWith( "WEB-INF/ext-web/docroot" ) ) //$NON-NLS-1$ { // look for packages file in first docroot IPath parentDocroot = webroot.getFullPath().removeFirstSegments( 1 ).removeLastSegments( 3 ); IFolder parentWebroot = this.javaProject.getProject().getFolder( parentDocroot ); if( parentWebroot.exists() ) { pluginPackageFile = parentWebroot.getFile( "WEB-INF/" + //$NON-NLS-1$ ILiferayConstants.LIFERAY_PLUGIN_PACKAGE_PROPERTIES_FILE ); } } } } } return pluginPackageFile; } }