/*******************************************************************************
* 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.ui.editor;
import com.liferay.ide.core.ILiferayConstants;
import com.liferay.ide.core.ILiferayPortal;
import com.liferay.ide.core.ILiferayProject;
import com.liferay.ide.core.LiferayCore;
import com.liferay.ide.core.properties.PortalPropertiesConfiguration;
import com.liferay.ide.server.core.ILiferayRuntime;
import com.liferay.ide.server.util.ServerUtil;
import com.liferay.ide.ui.LiferayUIPlugin;
import com.liferay.ide.ui.editor.LiferayPropertiesContentAssistProcessor.PropKey;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfigurationLayout;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.propertiesfileeditor.IPropertiesFilePartitions;
import org.eclipse.jdt.internal.ui.propertiesfileeditor.PropertiesFileSourceViewerConfiguration;
import org.eclipse.jface.internal.text.html.HTMLTextPresenter;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.ServerCore;
/**
* @author Gregory Amerson
* @author Simon Jiang
*/
@SuppressWarnings( "restriction" )
public class LiferayPropertiesSourceViewerConfiguration extends PropertiesFileSourceViewerConfiguration
{
private IContentAssistant assitant;
private PropKey[] propKeys;
public LiferayPropertiesSourceViewerConfiguration( ITextEditor editor )
{
super( JavaPlugin.getDefault().getJavaTextTools().getColorManager(),
JavaPlugin.getDefault().getCombinedPreferenceStore(), editor,
IPropertiesFilePartitions.PROPERTIES_FILE_PARTITIONING );
}
private IPath getAppServerPortalDir( final IEditorInput input )
{
IPath retval = null;
final IFile ifile = (IFile) input.getAdapter( IFile.class );
if( ifile != null )
{
final ILiferayProject project = LiferayCore.create( ifile.getProject() );
if( project != null )
{
final ILiferayPortal portal = project.adapt( ILiferayPortal.class );
if( portal != null )
{
retval = portal.getAppServerPortalDir();
}
}
}
else
{
File file = (File) input.getAdapter( File.class );
if( file == null && input instanceof FileStoreEditorInput )
{
FileStoreEditorInput fInput = (FileStoreEditorInput) input;
file = new File( fInput.getURI().getPath() );
}
if( file != null && file.exists() )
{
try
{
final IPath propsParentPath = new Path( file.getParentFile().getCanonicalPath() );
for( IRuntime runtime : ServerCore.getRuntimes() )
{
if( propsParentPath.equals( runtime.getLocation() ) ||
propsParentPath.isPrefixOf( runtime.getLocation() ) )
{
final ILiferayRuntime lr = ServerUtil.getLiferayRuntime( runtime );
retval = lr.getAppServerPortalDir();
break;
}
}
}
catch( Exception e )
{
LiferayUIPlugin.logError( "Unable to get portal language properties file", e );
}
}
}
return retval;
}
@Override
public IContentAssistant getContentAssistant( final ISourceViewer sourceViewer )
{
if( this.propKeys == null )
{
final IEditorInput input = this.getEditor().getEditorInput();
// first fine runtime location to get properties definitions
final IPath appServerPortalDir = getAppServerPortalDir( input );
final String propertiesEntry = getPropertiesEntry( input );
PropKey[] keys = null;
if( appServerPortalDir != null && appServerPortalDir.toFile().exists() )
{
try
{
final JarFile jar = new JarFile( appServerPortalDir.append( "WEB-INF/lib/portal-impl.jar" ).toFile() );
final ZipEntry lang = jar.getEntry( propertiesEntry );
keys = parseKeys( jar.getInputStream( lang ) );
jar.close();
}
catch( Exception e )
{
LiferayUIPlugin.logError( "Unable to get portal properties file", e );
}
}
else
{
return assitant;
}
final Object adapter = input.getAdapter( IFile.class );
if( adapter instanceof IFile && isHookProject( ( (IFile) adapter ).getProject() ) )
{
final ILiferayProject liferayProject = LiferayCore.create( ( (IFile) adapter ).getProject() );
final ILiferayPortal portal = liferayProject.adapt( ILiferayPortal.class );
if( portal != null )
{
final Set<String> hookProps = new HashSet<String>();
Collections.addAll( hookProps, portal.getHookSupportedProperties() );
final List<PropKey> filtered = new ArrayList<PropKey>();
for( PropKey pk : keys )
{
if( hookProps.contains( pk.getKey() ) )
{
filtered.add( pk );
}
}
keys = filtered.toArray( new PropKey[0] );
}
}
propKeys = keys;
}
if( propKeys != null && assitant == null )
{
final ContentAssistant ca = new ContentAssistant()
{
@Override
public IContentAssistProcessor getContentAssistProcessor( final String contentType )
{
return new LiferayPropertiesContentAssistProcessor( propKeys, contentType );
}
};
ca.setInformationControlCreator( getInformationControlCreator( sourceViewer ) );
assitant = ca;
}
return assitant;
}
public IInformationControlCreator getInformationControlCreator( ISourceViewer sourceViewer )
{
return new IInformationControlCreator()
{
public IInformationControl createInformationControl( Shell parent )
{
return new DefaultInformationControl( parent, new HTMLTextPresenter( true ) );
}
};
}
private String getPropertiesEntry( IEditorInput input )
{
String retval = null;
if( input.getName().equals( "system-ext.properties" ) )
{
retval = "system.properties";
}
else
{
retval = "portal.properties";
}
return retval;
}
private boolean isHookProject( IProject project )
{
final ILiferayProject lr = LiferayCore.create( project );
return lr != null && lr.getDescriptorFile( ILiferayConstants.LIFERAY_HOOK_XML_FILE ) != null;
}
private PropKey[] parseKeys( InputStream inputStream ) throws ConfigurationException, IOException
{
List<PropKey> parsed = new ArrayList<PropKey>();
final PortalPropertiesConfiguration config = new PortalPropertiesConfiguration();
config.load( inputStream );
inputStream.close();
final Iterator<?> keys = config.getKeys();
final PropertiesConfigurationLayout layout = config.getLayout();
while( keys.hasNext() )
{
final String key = keys.next().toString();
final String comment = layout.getComment( key );
parsed.add( new PropKey( key, comment == null ? null : comment.replaceAll( "\n", "\n<br/>" ) ) );
}
final PropKey[] parsedKeys = parsed.toArray( new PropKey[0] );
Arrays.sort( parsedKeys, new Comparator<PropKey>()
{
public int compare( PropKey o1, PropKey o2 )
{
return o1.getKey().compareTo( o2.getKey() );
}
});
return parsedKeys;
}
}