/******************************************************************************* * Copyright (c) 2012 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.ui.wizard.service; import java.io.ByteArrayInputStream; 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.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IType; import org.jboss.tools.common.EclipseUtil; import org.jboss.tools.common.ui.CommonUIPlugin; import org.jboss.tools.common.util.FileUtil; /** * * @author Viacheslav Kabanovich * */ public class RegisterServiceUtil { static final String META_INF_FOLDER_NAME = "META-INF"; //$NON-NLS-1$ static final String SERVICES_FOLDER_NAME = "services"; //$NON-NLS-1$ /** * Returns true if class %typeName% is listed in existing file * META-INF/services/%serviceType% in a Java source folder of the project. * * @param project * @param typeName * @param serviceType * @return * @throws CoreException */ public static boolean isServiceRegistered(IProject project, String typeName, String serviceType) { try { IContainer f = getServiceFolder(project, false); if(f == null || !f.exists()) { return false; } IFile file = f.getFile(new Path(serviceType)); return file.exists() && contains(FileUtil.readStream(file), typeName); } catch (CoreException e) { CommonUIPlugin.getDefault().logError(e); } return false; } /** * Returns true if %content% contains %typeName% separated from other text by whitespaces. * * @param content * @param typeName * @return */ private static boolean contains(String content, String typeName) { int p = content.indexOf(typeName); while(p >= 0) { int p0 = p; p += typeName.length(); if((p == content.length() || Character.isWhitespace(content.charAt(p))) && (p0 == 0 || Character.isWhitespace(content.charAt(p0 - 1))) ) { //registered already return true; } p = content.indexOf(typeName, p); } return false; } /** * Includes class %typeName% into file META-INF/services/%serviceType% * in a Java source folder of the project, if it is not registered yet. * If the file does not exist, it is created in the first Java source folder. * Existence of a Java source folder is evident by clients of this method: * (1) Service creation wizard that creates a new Java class in existing Java source; * (2) Service registration context action, that is run on selected IType or ICompilationUnit in existing Java source. * * * @param project * @param typeName * @param serviceType * @throws CoreException */ public static void registerService(IProject project, String typeName, String serviceType) throws CoreException { IContainer f = getServiceFolder(project, true); if(f != null) { IFile file = f.getFile(new Path(serviceType)); if(file.exists()) { String content = FileUtil.readStream(file); if(contains(content, typeName)) { return; } if(content.length() > 0 && !content.endsWith("\n")) { //$NON-NLS-1$ content += "\n"; //$NON-NLS-1$ } content += typeName; file.setContents(new ByteArrayInputStream(content.getBytes()), true, true, new NullProgressMonitor()); } else { String content = typeName; file.create(new ByteArrayInputStream(content.getBytes()), true, new NullProgressMonitor()); } } } public static void registerService(IType type, String serviceType) throws CoreException { IProject project = type.getJavaProject().getProject(); String typeName = type.getFullyQualifiedName(); registerService(project, typeName, serviceType); } /** * Returns the first existing 'META-INF/services' folder in a Java source folder, * or newly created 'META-INF/services' folder in an existing Java source folder if 'create' is set to true, * or null. * * @param project * @param create * @return * @throws CoreException */ private static IFolder getServiceFolder(IProject project, boolean create) throws CoreException { IContainer m = getMetaInf(project, create); if(m != null) { IFolder ss = m.getFolder(new Path(SERVICES_FOLDER_NAME)); if(!ss.exists()) { if(!create) { return null; } ss.create(true, true, new NullProgressMonitor()); } return ss; } return null; } /** * Returns the first existing META-INF folder in a Java source folder, * or newly created META-INF folder in an existing Java source folder if 'create' is set to true, * or null. * * @param project * @param create * @return * @throws CoreException */ private static IContainer getMetaInf(IProject project, boolean create) throws CoreException { IResource[] rs = EclipseUtil.getJavaSourceRoots(project); if(rs == null || rs.length == 0) { return null; } for (IResource r: rs) { IFolder f = ((IContainer)r).getFolder(new Path(META_INF_FOLDER_NAME)); if(f.exists()) return f; } if(!create) { return null; } IFolder f = ((IContainer)rs[0]).getFolder(new Path(META_INF_FOLDER_NAME)); f.create(true, true, new NullProgressMonitor()); return f; } }