/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * 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. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.adminapi.impl; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.teiid.adminapi.DataPolicy; import org.teiid.adminapi.Model; import org.teiid.adminapi.Translator; import org.teiid.adminapi.VDB; import org.teiid.core.util.CopyOnWriteLinkedHashMap; import org.teiid.core.util.StringUtil; import org.teiid.designer.annotation.Removed; import org.teiid.designer.annotation.Since; import org.teiid.designer.runtime.version.spi.TeiidServerVersion.Version; public class VDBMetaData extends AdminObjectImpl implements VDB, Cloneable { private static final String VERSION_DELIM = "."; //$NON-NLS-1$ private static final long serialVersionUID = -4723595252013356436L; /** * This ONLY exists to ensure that the serialisation framework * has access to the anonymous class VDBMetaData$1. * * IT SHOULD NEVER BE USED FOR ANYTHING ELSE!!! */ @Removed(Version.TEIID_8_0) private transient ListOverMap<ModelMetaData> sevenModels = new ListOverMap<ModelMetaData>(new KeyBuilder<ModelMetaData>() { private static final long serialVersionUID = 846247100420118961L; @Override public String getKey(ModelMetaData entry) { return entry.getName(); } }); /** * This ONLY exists to ensure that the serialisation framework * has access to the anonymous class VDBMetaData$2. * * IT SHOULD NEVER BE USED FOR ANYTHING ELSE!!! */ @Removed(Version.TEIID_8_0) private transient ListOverMap<VDBTranslatorMetaData> sevenTranslators = new ListOverMap<VDBTranslatorMetaData>(new KeyBuilder<VDBTranslatorMetaData>() { private static final long serialVersionUID = 3890502172003653563L; @Override public String getKey(VDBTranslatorMetaData entry) { return entry.getName(); } }); /** * This ONLY exists to ensure that the serialisation framework * has access to the anonymous class VDBMetaData$3. * * IT SHOULD NEVER BE USED FOR ANYTHING ELSE!!! */ @Removed(Version.TEIID_8_0) private transient ListOverMap<DataPolicyMetadata> sevenDataPolicies = new ListOverMap<DataPolicyMetadata>(new KeyBuilder<DataPolicyMetadata>() { private static final long serialVersionUID = 4954591545242715254L; @Override public String getKey(DataPolicyMetadata entry) { return entry.getName(); } }); private LinkedHashMap<String, ModelMetaData> models = new LinkedHashMap<String, ModelMetaData>(); private LinkedHashMap<String, VDBTranslatorMetaData> translators = new LinkedHashMap<String, VDBTranslatorMetaData>(); private LinkedHashMap<String, DataPolicyMetadata> dataPolicies = new LinkedHashMap<String, DataPolicyMetadata>(); @Since(Version.TEIID_8_0) private List<VDBImportMetadata> imports = new ArrayList<VDBImportMetadata>(2); @Since(Version.TEIID_8_0) private List<EntryMetaData> entries = new ArrayList<EntryMetaData>(2); private int version = 1; private String description; @Removed(Version.TEIID_8_0) private String fileUrl; @Since(Version.TEIID_8_0) private boolean xmlDeployment = false; private volatile VDB.Status status = VDB.Status.ACTIVE; private ConnectionType connectionType = VDB.ConnectionType.BY_VERSION; @Removed(Version.TEIID_8_0) private boolean removed; private long queryTimeout = Long.MIN_VALUE; @Since(Version.TEIID_8_0) private Set<String> importedModels = Collections.emptySet(); @Since(Version.TEIID_8_9) private Map<String, Boolean> visibilityOverrides = new HashMap<String, Boolean>(2); private LinkedHashMap<String, ModelMetaData> convertModels(ListOverMap<ModelMetaData> overMap) { LinkedHashMap<String, ModelMetaData> newMap = new LinkedHashMap<String, ModelMetaData>(); for (Entry<String, ModelMetaData> entry : overMap.getMap().entrySet()) { newMap.put(entry.getKey(), entry.getValue()); } return newMap; } private LinkedHashMap<String, DataPolicyMetadata> convertDataPolicies(ListOverMap<DataPolicyMetadata> overMap) { LinkedHashMap<String, DataPolicyMetadata> newMap = new LinkedHashMap<String, DataPolicyMetadata>(); for (Entry<String, DataPolicyMetadata> entry : overMap.getMap().entrySet()) { newMap.put(entry.getKey(), entry.getValue()); } return newMap; } private LinkedHashMap<String, VDBTranslatorMetaData> convertTranslators(ListOverMap<VDBTranslatorMetaData> overMap) { LinkedHashMap<String, VDBTranslatorMetaData> newMap = new LinkedHashMap<String, VDBTranslatorMetaData>(); for (Entry<String, VDBTranslatorMetaData> entry : overMap.getMap().entrySet()) { newMap.put(entry.getKey(), entry.getValue()); } return newMap; } /* * Helper method for serialization to deal with differences between Teiid 7 and 8 */ @SuppressWarnings("nls") private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { GetField readFields = ois.readFields(); /* models */ Object serModels = readFields.get("models", null); if (isLinkedHashMap(serModels)) { /* Teiid Version 8+ */ models = (LinkedHashMap<String, ModelMetaData>) serModels; } else if (isListOverMap(serModels)) { /* Teiid Version 7 */ ListOverMap<ModelMetaData> overMap = (ListOverMap<ModelMetaData>) serModels; models = convertModels(overMap); } else throw new IllegalStateException(); /* translators */ Object serTranslators = readFields.get("translators", null); if (isLinkedHashMap(serModels)) { /* Teiid Version 8+ */ translators = (LinkedHashMap<String, VDBTranslatorMetaData>) serTranslators; } else if (isListOverMap(serModels)) { /* Teiid Version 7 */ ListOverMap<VDBTranslatorMetaData> overMap = (ListOverMap<VDBTranslatorMetaData>) serTranslators; translators = convertTranslators(overMap); } else throw new IllegalStateException(); /* data policies */ Object serDataPolicies = readFields.get("dataPolicies", null); if (isLinkedHashMap(serModels)) { /* Teiid Version 8+ */ dataPolicies = (LinkedHashMap<String, DataPolicyMetadata>) serDataPolicies; } else if (isListOverMap(serModels)) { /* Teiid Version 7 */ ListOverMap<DataPolicyMetadata> overMap = (ListOverMap<DataPolicyMetadata>) serDataPolicies; dataPolicies = convertDataPolicies(overMap); } else throw new IllegalStateException(); version = readFields.get("version", 1); description = (String) readFields.get("description", null); /* Teiid 7 */ fileUrl = (String) readFields.get("fileUrl", null); /* Teiid 8+ */ imports = (List<VDBImportMetadata>) readFields.get("imports", null); entries = (List<EntryMetaData>) readFields.get("entries", null); xmlDeployment = readFields.get("xmlDeployment", false); status = (Status) readFields.get("status", null); connectionType = (ConnectionType) readFields.get("connectionType", null); removed = readFields.get("removed", false); queryTimeout = readFields.get("queryTimeout", Long.MIN_VALUE); importedModels = (Set<String>) readFields.get("importedModels", null); } public String getFullName() { return getName() + VERSION_DELIM + getVersion(); } @Override public ConnectionType getConnectionType() { return this.connectionType; } public void setConnectionType(ConnectionType allowConnections) { this.connectionType = allowConnections; } public void setConnectionType(String allowConnections) { this.connectionType = ConnectionType.valueOf(allowConnections); } @Override public Status getStatus() { return this.status; } public synchronized void setStatus(Status s) { this.notifyAll(); this.status = s; } public void setStatus(String s) { setStatus(Status.valueOf(s)); } @Override public int getVersion() { return this.version; } public void setVersion(int version) { this.version = version; } @Override @Removed(Version.TEIID_8_0) public String getUrl() { return this.fileUrl; } @Removed(Version.TEIID_8_0) public void setUrl(String url) { this.fileUrl = url; } @Removed(Version.TEIID_8_0) public void setUrl(URL url) { this.setUrl(url.toExternalForm()); String path = url.getPath(); if (path.endsWith("/")) { //$NON-NLS-1$ path = path.substring(0, path.length() - 1); } String fileName = StringUtil.getLastToken(path, "/"); //$NON-NLS-1$ String[] parts = fileName.split("\\."); //$NON-NLS-1$ if (parts[0].equalsIgnoreCase(getName()) && parts.length >= 3) { try { int fileVersion = Integer.parseInt(parts[parts.length - 2]); this.setVersion(fileVersion); } catch (NumberFormatException e) { } } } @Override public List<Model> getModels(){ return new ArrayList<Model>(this.models.values()); } public LinkedHashMap<String, ModelMetaData> getModelMetaDatas() { return this.models; } /** * @param models */ public void setModels(Collection<ModelMetaData> models) { this.models.clear(); for (ModelMetaData obj : models) { addModel(obj); } } public ModelMetaData addModel(ModelMetaData m) { return this.models.put(m.getName(), m); } @Override public List<Translator> getOverrideTranslators() { return new ArrayList<Translator>(this.translators.values()); } public LinkedHashMap<String, VDBTranslatorMetaData> getOverrideTranslatorsMap() { return this.translators; } public void setOverrideTranslators(List<Translator> translators) { for (Translator t: translators) { this.translators.put(t.getName(), (VDBTranslatorMetaData)t); } } public void addOverideTranslator(VDBTranslatorMetaData t) { this.translators.put(t.getName(), t); } public boolean isOverideTranslator(String name) { return this.translators.containsKey(name); } @Override public String getDescription() { return this.description; } public void setDescription(String desc) { this.description = desc; } @Override public List<String> getValidityErrors(){ List<String> allErrors = new ArrayList<String>(); for (ModelMetaData model:this.models.values()) { List<ModelMetaData.Message> errors = model.getMessages(); if (errors != null && !errors.isEmpty()) { for (ModelMetaData.Message m:errors) { if (m.getSeverity() == ModelMetaData.Message.Severity.ERROR) { allErrors.add(m.getValue()); } } } } return allErrors; } @Override public boolean isValid() { return status == Status.ACTIVE && !hasErrors(); } public boolean hasErrors() { for (ModelMetaData model : this.models.values()) { if (model.hasErrors()) { return true; } } return false; } public String toString() { return getName()+VERSION_DELIM+getVersion()+ models.values(); } @Override public boolean isVisible(String modelName) { ModelMetaData model = getModel(modelName); if (model == null) { return true; } if (!visibilityOverrides.isEmpty()) { Boolean result = visibilityOverrides.get(modelName); if (result != null) { return result; } } return model.isVisible(); } public ModelMetaData getModel(String modelName) { return this.models.get(modelName); } /** * If this is a *-vdb.xml deployment * @return */ public boolean isXmlDeployment() { return xmlDeployment; } public void setXmlDeployment(boolean dynamic) { this.xmlDeployment = dynamic; } @Override public List<DataPolicy> getDataPolicies(){ return new ArrayList<DataPolicy>(this.dataPolicies.values()); } /** * This method is required by the Management framework to write the mappings to the persistent form. The actual assignment is done * in the VDBMetaDataClassInstancefactory * @param policies */ public void setDataPolicies(List<DataPolicy> policies){ this.dataPolicies.clear(); for (DataPolicy policy:policies) { this.dataPolicies.put(policy.getName(), (DataPolicyMetadata)policy); } } public DataPolicyMetadata addDataPolicy(DataPolicyMetadata policy){ return this.dataPolicies.put(policy.getName(), policy); } public LinkedHashMap<String, DataPolicyMetadata> getDataPolicyMap() { return this.dataPolicies; } public VDBTranslatorMetaData getTranslator(String name) { return this.translators.get(name); } public boolean isPreview() { return Boolean.valueOf(getPropertyValue("preview")); //$NON-NLS-1$ } public long getQueryTimeout() { if (queryTimeout == Long.MIN_VALUE) { String timeout = getPropertyValue("query-timeout"); //$NON-NLS-1$ if (timeout != null) { queryTimeout = Math.max(0, Long.parseLong(timeout)); } else { queryTimeout = 0; } } return queryTimeout; } public List<VDBImportMetadata> getVDBImports() { return imports; } public Set<String> getImportedModels() { return importedModels; } public void setImportedModels(Set<String> importedModels) { this.importedModels = importedModels; } @Override public List<EntryMetaData> getEntries() { return this.entries; } public void setEntries(List<EntryMetaData> entries) { this.entries = entries; } @Override public VDBMetaData clone() { try { VDBMetaData clone = (VDBMetaData) super.clone(); clone.models = new LinkedHashMap<String, ModelMetaData>(this.models); clone.attachments = new CopyOnWriteLinkedHashMap<Class<?>, Object>(); clone.attachments.putAll(attachments); clone.dataPolicies = new LinkedHashMap<String, DataPolicyMetadata>(dataPolicies); clone.visibilityOverrides = new HashMap<String, Boolean>(visibilityOverrides); return clone; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } @Since(Version.TEIID_8_9) public void setVisibilityOverride(String name, boolean visible) { this.visibilityOverrides.put(name, visible); } @Since(Version.TEIID_8_9) public Map<String, Boolean> getVisibilityOverrides() { return visibilityOverrides; } }