/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and 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: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.model.files.handlers; import java.io.*; import java.text.MessageFormat; import java.util.*; import org.eclipse.core.resources.IResource; import org.eclipse.swt.widgets.Display; import org.jboss.tools.common.meta.XMapping; import org.jboss.tools.common.meta.XModelMetaData; import org.jboss.tools.common.meta.action.*; import org.jboss.tools.common.meta.action.impl.*; import org.jboss.tools.common.meta.action.impl.handlers.DefaultCreateHandler; import org.jboss.tools.common.meta.impl.XMetaDataConstants; import org.jboss.tools.common.model.*; import org.jboss.tools.common.model.filesystems.impl.*; import org.jboss.tools.common.model.loaders.EntityRecognizerContext; import org.jboss.tools.common.model.loaders.impl.MappedEntityRecognizer; import org.jboss.tools.common.model.plugin.ModelMessages; import org.jboss.tools.common.model.util.*; import org.jboss.tools.common.util.FileUtil; public class CreateFileSupport extends SpecialWizardSupport { public static String INITIAL_FOLDER_PROPERTY = "initialFolder"; //$NON-NLS-1$ public static String INITIAL_FILE_PROPERTY = "initialFile"; //$NON-NLS-1$ static final String ATTR_TEMPLATE = "template"; //$NON-NLS-1$ static final String ATTR_FOLDER = "folder"; //$NON-NLS-1$ protected TargetHolder targetHolder = new TargetHolder(); TreeMap<String,String> versionEntities = new TreeMap<String,String>(); boolean useVersions = false; public static interface DefaultVersionResolver { public String resolve(String[] versionList, XModelObject context); } public void reset() { targetHolder.setAction(action); if(hasTemplate()) { String[] s = getPageTemplateList(); setValueList(0, ATTR_TEMPLATE, s); if(s.length > 0) { //take from preferences String defaultPageTemplate = getDefaultPageTemplate(); if (defaultPageTemplate == null) { defaultPageTemplate = s[0]; } else { boolean bFound = false; for (int i = 0; i < s.length && !bFound; i++) { if (s[i].equals(defaultPageTemplate)) bFound = true; } if (!bFound) defaultPageTemplate = s[0]; } setAttributeValue(0, ATTR_TEMPLATE, defaultPageTemplate); } } targetHolder.target = getTarget(); IResource r = (IResource)getTarget().getAdapter(IResource.class); if(r == null) { setAttributeValue(0, ATTR_FOLDER, ""); //$NON-NLS-1$ targetHolder.revalidate(null); } else { targetHolder.revalidate(r.getFullPath().toString()); setAttributeValue(0, ATTR_FOLDER, "" + targetHolder.path); //$NON-NLS-1$ } String initialFolder = p.getProperty(INITIAL_FOLDER_PROPERTY); if(initialFolder != null && initialFolder.length() > 0) { setAttributeValue(0, ATTR_FOLDER, initialFolder); } String initialFile = p.getProperty(INITIAL_FILE_PROPERTY); if(initialFile != null && initialFile.length() > 0) { setAttributeValue(0, XModelObjectConstants.ATTR_NAME, initialFile); } initVersions(); } protected String getDefaultPageTemplate() { return null; } void initVersions() { useVersions = false; versionEntities.clear(); XModelMetaData meta = getTarget().getModel().getMetaData(); XMapping m = meta.getMapping("FileVersions"); //$NON-NLS-1$ if(m == null) return; String entityVersion = action.getProperty("entityVersion"); //$NON-NLS-1$ if(entityVersion == null || entityVersion.length() == 0) return; if(getAttributeValue(0, "version") == null) return; //$NON-NLS-1$ useVersions = true; String[] keys = m.getKeys(); for (int i = 0; i < keys.length; i++) { if(!keys[i].startsWith(entityVersion)) continue; String entity = m.getValue(keys[i]); if(meta.getEntity(entity) == null) continue; String version = keys[i].substring(entityVersion.length()); versionEntities.put(version, entity); } if(versionEntities.size() == 0 && action.getProperty(XMetaDataConstants.ENTITY) != null) { versionEntities.put("default", action.getProperty(XMetaDataConstants.ENTITY)); //$NON-NLS-1$ } String[] versionList = (String[])versionEntities.keySet().toArray(new String[0]); setValueList(0, "version", versionList); //$NON-NLS-1$ if(versionList.length > 0) { String defaultVersion = versionList[versionList.length - 1]; String defaultVersionResolver = action.getProperty("defaultVersionResolver"); //$NON-NLS-1$ if(defaultVersionResolver != null) { DefaultVersionResolver resolver = (DefaultVersionResolver)ModelFeatureFactory.getInstance().createFeatureInstance(defaultVersionResolver); if(resolver != null) { String d = resolver.resolve(versionList, getTarget()); if(d != null) defaultVersion = d; } } setAttributeValue(0, "version", defaultVersion); //$NON-NLS-1$ } } private boolean hasTemplate() { return findAttribute(0, ATTR_TEMPLATE) != null; } public void action(String name) throws XModelException { if(FINISH.equals(name)) { if(!checkResource()) return; execute(); setFinished(true); } else if(CANCEL.equals(name)) { setFinished(true); } else if(HELP.equals(name)) { help(); } } public String[] getActionNames(int stepId) { return new String[]{FINISH, CANCEL, HELP}; } protected void execute() throws XModelException { Properties p = extractStepData(0); String path = p.getProperty(XModelObjectConstants.ATTR_NAME); path = revalidatePath(path); XModelObject f = createFile(path); if(f != null) targetHolder.saveLastPath(); if(f != null) open(f); } protected boolean checkResource() { if(targetHolder.addPath.length() == 0) return true; ServiceDialog d = getTarget().getModel().getService(); String message = MessageFormat.format( "Folder {0} does not exist. Do you want to create it?", targetHolder.path); int q = d.showDialog(ModelMessages.WARNING, message, new String[]{SpecialWizardSupport.OK, SpecialWizardSupport.CANCEL}, null, ServiceDialog.QUESTION); return q == 0; } public boolean isFieldEditorEnabled(int stepId, String name, Properties values) { String path = values.getProperty(XModelObjectConstants.ATTR_NAME); boolean c = canCreateFile(path); if(name.equals(ATTR_TEMPLATE)) { return c; } return true; } public boolean canCreateFile(String path) { if(targetHolder.target == null) return false; if(path == null || path.length() == 0 || path.indexOf('*') >= 0) return false; return isCorrectPath(path) && !fileExists(path); } boolean isCorrectPath(String path) { path = revalidatePath(path); if(path == null || path.equals(XModelObjectConstants.SEPARATOR) || path.indexOf("//") >= 0) return false; //$NON-NLS-1$ return true; } boolean fileExists(String path) { if(path == null || targetHolder.target == null) return false; path = revalidatePath(path); if(path.startsWith(XModelObjectConstants.SEPARATOR)) path = path.substring(1); return targetHolder.target.getChildByPath(path) != null; } protected String revalidatePath(String path) { if(path == null || path.length() == 0) return path; if(!path.startsWith(XModelObjectConstants.SEPARATOR)) path = XModelObjectConstants.SEPARATOR + path; String extension = "." + action.getProperty(XModelObjectConstants.ATTR_NAME_EXTENSION); //$NON-NLS-1$ if(path.lastIndexOf('.') < 0) { path += extension; } else { String ext = path.substring(path.lastIndexOf('.')); if(!ext.equals(extension) && extension.length() > 1) path += extension; } if(targetHolder.addPath.length() > 0) { path = targetHolder.addPath + path; } return path; } protected XModelObject createFile(String path) throws XModelException { if(!canCreateFile(path)) return null; try { String body = getTemplateBody(); body = modifyBody(body); return createFile(targetHolder.target, path, body, extractStepData(0)); } catch (IOException e) { throw new XModelException(e); } } protected String getTemplateBody() throws IOException { File templateFile = null; String template = getAttributeValue(0, ATTR_TEMPLATE); if(template != null && template.trim().length() > 0) { templateFile = findTemplate(template.trim()); if(templateFile == null || !templateFile.isFile()) throw new IOException( MessageFormat.format("Template {0} is not found.", template)); } return (templateFile == null) ? "" : FileUtil.readFile(templateFile); //$NON-NLS-1$ } protected String modifyBody(String body) throws IOException { return body; } protected void open(final XModelObject f) { Display.getDefault().asyncExec(new Runnable() { public void run() { FindObjectHelper.findModelObject(f, FindObjectHelper.EVERY_WHERE); } }); } XModelObject createFile(XModelObject fs, String path, String body, Properties p) throws XModelException { StringTokenizer st = new StringTokenizer(path, XModelObjectConstants.SEPARATOR); int c = st.countTokens(), i = 0; while(i < c - 1) { String s = st.nextToken(); XModelObject o = fs.getChildByPath(s); if(o == null) { o = fs.getModel().createModelObject("FileFolder", null); //$NON-NLS-1$ o.setAttributeValue(XModelObjectConstants.ATTR_NAME, s); DefaultCreateHandler.addCreatedObject(fs, o, FindObjectHelper.IN_NAVIGATOR_ONLY); ((FolderImpl)o).save(); } fs = o; i++; } String s = st.nextToken(); int dot = s.lastIndexOf('.'); String n = s.substring(0, dot); String e = s.substring(dot + 1); String entity = getFileEntity(e); XModelObject f = XModelObjectLoaderUtil.createValidObject(fs.getModel(), entity, p); f.setAttributeValue(XModelObjectConstants.ATTR_NAME, n); f.setAttributeValue(XModelObjectConstants.ATTR_NAME_EXTENSION, e); if(body != null) f.setAttributeValue(XModelObjectConstants.ATTR_NAME_BODY, body); f = modifyCreatedObject(f); XModelObject fq = fs.getChildByPath(f.getPathPart()); if(fq != null) return fq; DefaultCreateHandler.addCreatedObject(fs, f, FindObjectHelper.IN_NAVIGATOR_ONLY); if(f instanceof FileAnyImpl && f.getModelEntity().getAttribute(XModelObjectConstants.ATTR_NAME_ENCODING) != null) { String txt = ((FileAnyImpl)f).getAsText(); String enc = XModelObjectLoaderUtil.getEncoding(txt); if(enc != null) f.setAttributeValue(XModelObjectConstants.ATTR_NAME_ENCODING, enc); } String modelPath = f.getPath(); ((FolderImpl)fs).saveChild(f); fs.getModel().update(); if(f.getParent() == null) { //entity could change after saving child. f = f.getModel().getByPath(modelPath); } if(f != null) getProperties().put("created", f); //$NON-NLS-1$ return f; } protected String getFileEntity(String extension) { if(useVersions) { String version = getAttributeValue(0, "version"); //$NON-NLS-1$ String entity = version == null ? null : (String)versionEntities.get(version); if(entity != null) return entity; } String entity = null; if(extension.equals(action.getProperty(XModelObjectConstants.ATTR_NAME_EXTENSION))) { entity = action.getProperty(XMetaDataConstants.ENTITY); } if(entity == null) { entity = new MappedEntityRecognizer().getEntityName(new EntityRecognizerContext(extension)); } if(entity != null && getTarget().getModel().getMetaData().getEntity(entity) != null) { return entity; } return "FileAny"; //$NON-NLS-1$ } protected XModelObject modifyCreatedObject(XModelObject o) { return o; } protected File findTemplate(String name) { return null; } public String[] getPageTemplateList() { return new String[0]; } protected final XModelObject getTargetFolder() { return targetHolder.target; } protected DefaultWizardDataValidator validator = createValidator(); public WizardDataValidator getValidator(int step) { validator.setSupport(this, step); return validator; } protected DefaultWizardDataValidator createValidator() { return new Validator(); } protected class Validator extends DefaultWizardDataValidator { public void validate(Properties data) { String folder = data.getProperty(ATTR_FOLDER); targetHolder.revalidate(folder); message = null; validateFolderName(); if(message != null) return; validateFileName(data); if(message != null) return; String template = data.getProperty(ATTR_TEMPLATE); if(template != null && template.trim().length() > 0) { File templateFile = findTemplate(template.trim()); if(templateFile == null || !templateFile.isFile()) { message = "Template does not exist."; } } if(message != null) return; super.validate(data); } String FORBIDDEN_INDICES = "\"\n\t*\\/:<>?|"; //$NON-NLS-1$ protected void validateFileName(Properties data) { if(message != null) return; String fileName = data.getProperty(XModelObjectConstants.ATTR_NAME); if(fileName == null || fileName.length() == 0) return; if(fileName.equals(".")) { //$NON-NLS-1$ message = "Incorrect file name."; } else if(fileName.endsWith(".") && fileName.indexOf('.') != fileName.lastIndexOf('.')) { //$NON-NLS-1$ message = "File name must not end in a period."; } else { for (int i = 0; i < FORBIDDEN_INDICES.length(); i++) { if(fileName.indexOf(FORBIDDEN_INDICES.charAt(i)) >= 0) { message = MessageFormat.format( "File name must not contain character {0} .", FORBIDDEN_INDICES.charAt(i)); return; } } } } String FORBIDDEN_FOLDER_LETTERS = "\"\n\t*:<>?|"; //$NON-NLS-1$ private void validateFolderName() { if(targetHolder.addPath.length() == 0) return; for (int i = 0; i < FORBIDDEN_FOLDER_LETTERS.length(); i++) { if(targetHolder.addPath.indexOf(FORBIDDEN_FOLDER_LETTERS.charAt(i)) >= 0) { message = MessageFormat.format( "Folder name must not contain character {0} .", FORBIDDEN_FOLDER_LETTERS.charAt(i)); return; } } } protected void validateAddFile(XEntityData[] ds, Properties data) { CreateFileHandler.validateNameAndExtension(action, data, null); if(targetHolder.target != null) { String entity = action.getProperty(XMetaDataConstants.ENTITY); if(entity == null) entity = getEntityData()[step].getModelEntity().getName(); if(targetHolder.addPath == null || targetHolder.addPath.length() == 0) { if(!checkChild(targetHolder.target, entity, data)) return; } } else { message = "Cannot create file in specified folder."; } } } public String getFocusAttribute(int stepId) { if(stepId == 0) { return XModelObjectConstants.ATTR_NAME; } return super.getFocusAttribute(stepId); } }