/** * <p>Copyright: Copyright (c) 2009</p> * <p>Company: �������ӹɷ����޹�˾</p> */ package com.hundsun.ares.studio.internal.core; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import com.hundsun.ares.studio.core.ARESModelException; import com.hundsun.ares.studio.core.IARESBundle; import com.hundsun.ares.studio.core.IARESBundleInfo; import com.hundsun.ares.studio.core.IARESElement; import com.hundsun.ares.studio.core.IARESModule; import com.hundsun.ares.studio.core.IARESModuleRoot; import com.hundsun.ares.studio.core.IARESProjectProperty; import com.hundsun.ares.studio.core.IARESResource; import com.hundsun.ares.studio.core.IBasicReferencedLibInfo; import com.hundsun.ares.studio.core.IDependenceDescriptor; import com.hundsun.ares.studio.core.IReferencedLibrary; import com.hundsun.ares.studio.core.IResPathEntry; import com.hundsun.ares.studio.core.model.extendable.IExtendAbleModel; import com.hundsun.ares.studio.core.registry.ARESResRegistry; import com.hundsun.ares.studio.core.registry.IResDescriptor; import com.hundsun.ares.studio.core.util.Util; /** * ���ð� * @author sundl */ public abstract class ReferencedLibrary extends Openable implements IReferencedLibrary { private static final Logger logger = Logger.getLogger(ReferencedLibrary.class.getName()); protected IResPathEntry entry; /** * @param parent */ public ReferencedLibrary(IARESElement parent, IResPathEntry entry) { super(parent); this.entry = entry; } /* (non-Javadoc) * @see com.hundsun.ares.devtool.common.core.IReferencedLibrary#getRoots() */ public IARESModuleRoot[] getRoots() throws ARESModelException{ IARESElement[] children = getChildren(); IARESModuleRoot[] roots = new IARESModuleRoot[children.length]; System.arraycopy(children, 0, roots, 0, children.length); return roots; } public IARESModuleRoot getRoot(IPath path) { try { for (IARESModuleRoot root : getRoots()) { if (root.getPath().toString().equals(path.toString())) return root; } } catch (ARESModelException e) { e.printStackTrace(); } return null; } public IResPathEntry getResPathEntry() { return entry; } protected abstract ZipFile getZipFile() throws ZipException, IOException ; /* (non-Javadoc) * @see com.hundsun.ares.devtool.v2.internal.core.Openable#buildStructure(com.hundsun.ares.devtool.v2.internal.core.OpenableElementInfo) */ @Override protected boolean buildStructure(OpenableElementInfo info) throws ARESModelException { logger.info("Start Referenced Library: " + getElementName() + ", project: " + getARESProject().getElementName()); ReferencedLibraryInfo libInfo = (ReferencedLibraryInfo)info; ZipFile zipFile = null; try { // zipFile = new ZipFile(new File(file.getLocation().toOSString())); zipFile = getZipFile(); ZipEntry entry = zipFile.getEntry(PROPERTIE_FILE); if (entry == null) { // ��.aar�ļ��IJŻ������û�о���Ϊ�ļ���ʽ����ȷ logFileFormatNotValid(null); } else { // ��ȡ������Ϣ logger.debug("Read RerencedLib description file(.aar) ..."); ReferencedLibrayUtil.readRefLibInfo(libInfo, zipFile.getInputStream(entry), getARESProject()); // �����project.xml��Ҳ��һ�� ZipEntry projEntry = zipFile.getEntry(IARESProjectProperty.PRO_FILE); if (projEntry != null) ReferencedLibrayUtil.readExtendedInfo((IExtendAbleModel)libInfo.getBasicInfo(), zipFile.getInputStream(projEntry)); // �����ṹ logger.debug("Resolve referneced lib structure..."); resolveRefLibStructure(libInfo, zipFile); } } catch (Exception e) { logFileFormatNotValid(e); throw new ARESModelException(e, IStatus.ERROR); } finally { try { if(null != zipFile){ zipFile.close(); } } catch (IOException e) { logger.warn("close zip file failed...", e); } } return true; } // �����ṹ private void resolveRefLibStructure(ReferencedLibraryInfo info, ZipFile zipFile) { // �ݴ�� ģ���--->ģ���б� ӳ�� Map<IARESModuleRoot, List<IARESModule>> rootsInfo = new HashMap<IARESModuleRoot, List<IARESModule>>(); Map<IARESModule, List<IARESResource>> modulesInfo = new HashMap<IARESModule, List<IARESResource>>(); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); logger.debug("process entry: " + entry); // if on res-path IResPathEntry respathEntry = isOnRespath(entry, info.getRespath()); if (respathEntry != null) { String name = entry.getName(); IPath zipEntryPath = new Path(name); IPath resPathEntryPath = respathEntry.getPath(); // since it is on the res-path, there's always a module-root logger.debug("create module root..."); IARESModuleRoot root = new ArchiveARESModuleRoot(this, resPathEntryPath, respathEntry.getType()); logger.debug("create complete."); if (rootsInfo.containsKey(root)) { // do nothing } else { // an module root is found, add into the cache logElementFound("Module Root", zipEntryPath); rootsInfo.put(root, new ArrayList<IARESModule>()); } // if a directory, maybe a module root, a module, or non-ares element if (entry.isDirectory()) { if (zipEntryPath.equals(resPathEntryPath)) { // root // do nothing, added already } else if (zipEntryPath.segmentCount() > resPathEntryPath.segmentCount()) { IPath suffixPath = zipEntryPath.removeFirstSegments(resPathEntryPath.segmentCount()); IARESModule module = testModule(root, suffixPath); if (module != null) { // module List<IARESModule> moduleList = rootsInfo.get(root); resolveModule(module, moduleList); } else { // nothing, just log it. //logger.fine("Zip entry : " + zipEntryPath + " is not a valid common element, ignored."); logPathIgnored(zipEntryPath); } } } else { // not a directory, a file... String fileName = zipEntryPath.lastSegment(); IResDescriptor desc = getResDescriptor(fileName); if (desc != null) { IPath modulePath = zipEntryPath.removeFirstSegments(resPathEntryPath.segmentCount()).removeLastSegments(1); IARESModule module = testModule(root, modulePath); if (module != null) { List<IARESModule> moduleList = rootsInfo.get(root); resolveModule(module, moduleList); List<IARESResource> resList; if (!modulesInfo.containsKey(module)) { resList = new ArrayList<IARESResource>(); modulesInfo.put(module, resList); } else { resList = modulesInfo.get(module); } resList.add(new ArchiveARESResource(module, fileName)); logElementFound("Resource", zipEntryPath); } } else logPathIgnored(zipEntryPath); } } } info.rootsInfo = rootsInfo; info.moduleInfo = modulesInfo; info.setChildren(rootsInfo.keySet().toArray(new IARESElement[0])); } private IResDescriptor getResDescriptor(String filename) { // ȫ������ // Ӧ���ȼ���ļ�ȫ�����ټ����չ�� IResDescriptor desc = ARESResRegistry.getInstance().getResDescriptor(filename); if (desc == null) { String ext = StringUtils.substringAfterLast(filename, "."); desc = ARESResRegistry.getInstance().getResDescriptor(ext); } return desc; } /** * try to resolve the given path as a module. if succeed, return the module. * @param root the module root which the module belongs to * @param path the path * @return if the give path can be map to a module, return the module, or return null */ private IARESModule testModule(IARESModuleRoot root, IPath path) { String[] names = path.segments(); if (Util.isValidNamesForModule(names)) { return new ArchiveARESModule(root, names); } return null; } /* * Java ��ZIP API��ѹ���ļ���ʱ�򣬲�����ļ�����Ϊ������Entry����zip�ļ��������ڽ�����һ�� * ģ���ʱ��ͬʱ��Ҫ�Զ��Ѹ�ģ��һ��һ���Զ����������������ڴ��л�ȱ��ijЩģ�����Ϣ�� */ private void resolveModule(IARESModule module, List<IARESModule> moduleList) { if (!moduleList.contains(module)) { moduleList.add(module); } IARESModule parentModule = getParentModule((ArchiveARESModule)module); if (parentModule != null) { resolveModule(parentModule, moduleList); } } private IARESModule getParentModule(ArchiveARESModule module) { IARESModuleRoot root = module.getRoot(); String[] names = module.names; if (names.length > 1) { String[] parentNames = new String[names.length - 1]; System.arraycopy(names, 0, parentNames, 0, names.length - 1); return new ArchiveARESModule(root, parentNames); } return null; } // �Ƿ���respath��,����ڣ��򷵻ض�Ӧ��res path entry�����򷵻�null private IResPathEntry isOnRespath(ZipEntry ze, List<IResPathEntry> respath) { for (IResPathEntry entry : respath) { IPath ePath = new Path(ze.getName()); IPath rPath = entry.getPath(); // ����ģ�������Ҳ��Ϊ����res-path�ϵ� if (rPath.isPrefixOf(ePath) /*&& rPath.segmentCount() < ePath.segmentCount()*/) { return entry; } } return null; } private void logFileFormatNotValid(Exception e) { if (e != null) { logger.warn(getElementName() + " is not a valid Ares Archive file", e); } else logger.warn(getElementName() + " is not a valid Ares Archive file"); } // ��־��¼ָ�����͵�Ԫ�ر�ʶ�� private void logElementFound(String type, IPath path) { if (logger.isInfoEnabled()) { logger.info(type + " is found, path is: " + path); } } // ��־��¼ָ����pathû�б����� private void logPathIgnored(IPath path) { if (logger.isInfoEnabled()) logger.info("Path is ignored: " + path); } /* (non-Javadoc) * @see com.hundsun.ares.devtool.v2.internal.core.Openable#createElementInfo() */ @Override protected Object createElementInfo() { return new ReferencedLibraryInfo(); } // /* (non-Javadoc) // * @see com.hundsun.ares.devtool.v2.internal.core.Openable#validateExistence(org.eclipse.core.resources.IResource) // */ // @Override // protected IStatus validateExistence(IResource underlyingResource) { // if (onResPath() && file.exists()) // return ARESModelStatus.VERIFIED_OK; // // return newDoesNotExistStatus(); // } // // private boolean onResPath() { // for (IResPathEntry entry : getARESProject().getRawResPath()) { // if (entry.getPath().equals(file.getProjectRelativePath())) // return true; // } // return false; // } // // /* (non-Javadoc) // * @see com.hundsun.ares.studio.core.IARESElement#getCorrespondingResource() // */ // public IResource getCorrespondingResource() throws ARESModelException { // return file; // } // // /* (non-Javadoc) // * @see com.hundsun.ares.studio.core.IARESElement#getElementName() // */ // public String getElementName() { // return file.getName(); // } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IARESElement#getElementType() */ public int getElementType() { return REF_LIBRAYR; } // /* (non-Javadoc) // * @see com.hundsun.ares.studio.core.IARESElement#getPath() // */ // public IPath getPath() { // return file.getFullPath(); // } // /* (non-Javadoc) // * @see com.hundsun.ares.studio.core.IARESElement#getResource() // */ // public IResource getResource() { // return file; // } /* (non-Javadoc) * @see com.hundsun.ares.studio.internal.core.ARESElement#getHandleMementoDelimiter() */ @Override protected char getHandleMementoDelimiter() { return AEM_LIB; } protected void getHandleMemento(StringBuffer buff) { ((ARESElement)getParent()).getHandleMemento(buff); buff.append(getHandleMementoDelimiter()); escapeMementoName(buff, getPath().toString()); } /* (non-Javadoc) * @see com.hundsun.ares.studio.internal.core.ARESElement#getHandleFromMemento(java.lang.String, com.hundsun.ares.studio.internal.core.MementoTokenizer) */ @Override public IARESElement getHandleFromMemento(String token, MementoTokenizer memento) { switch (token.charAt(0)) { case AEM_MODULEROOT: //if (memento.hasMoreTokens()) { token = memento.nextToken(); //} Path rootPath = new Path(token); ARESElement root = (ARESElement) getRoot(rootPath); if (root != null) { if ((token = memento.nextToken()) != null && token.charAt(0) == AEM_MODULE) { return root.getHandleFromMemento(token, memento); } else { return root.getHandleFromMemento(memento); } } break; } return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IReferencedLibrary#getBasicInfo() */ public IBasicReferencedLibInfo getBasicInfo() { try { ReferencedLibraryInfo info = (ReferencedLibraryInfo) getElementInfo(); if (info != null) { return info.getBasicInfo(); } } catch (ARESModelException e) { e.printStackTrace(); } return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getDependencies() */ public List<IDependenceDescriptor> getDependencyDescriptors() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getDependencyDescriptors(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getPublishTime() */ public String getPublishTime() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getPublishTime(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getNote() */ public String getNote() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getNote(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getName() */ public String getName() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getName(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getPublisher() */ public String getPublisher() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getPublisher(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getContact() */ public String getContact() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getContact(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getProvider() */ public String getProvider() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getProvider(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getVersion() */ public String getVersion() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getVersion(); return null; } public String getType() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getType(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IBasicReferencedLibInfo#getId() */ public String getId() { IBasicReferencedLibInfo info = getBasicInfo(); if (info != null) return getBasicInfo().getId(); return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IARESBundle#getInfo() */ @Override public IARESBundleInfo getInfo() { return (IARESBundleInfo) getBasicInfo(); } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IARESBundle#getResources(java.lang.String) */ @Override public IARESResource[] getResources(String name) throws ARESModelException { List<IARESResource> results = new ArrayList<IARESResource>(); for (IARESResource res : getResources()) { if (res.getElementName().equals(name)) { results.add(res); } } return results.toArray(new IARESResource[0]); } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IARESBundle#getResources(java.lang.String[]) */ @Override public IARESResource[] getResources(String[] types) throws ARESModelException { List<IARESResource> results = new ArrayList<IARESResource>(); for (IARESModuleRoot root : getModuleRoots()) { results.addAll(Arrays.asList(root.getResources(types))); } return results.toArray(new IARESResource[0]); } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IARESBundle#getResources() */ @Override public IARESResource[] getResources() throws ARESModelException { List<IARESResource> results = new ArrayList<IARESResource>(); for (IARESModuleRoot root : getModuleRoots()) { results.addAll(Arrays.asList(root.getResources())); } return results.toArray(new IARESResource[0]); } public IARESModuleRoot[] getModuleRoots() throws ARESModelException { return getRoots(); } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IARESBundle#getModuleRoot(java.lang.String) */ @Override public IARESModuleRoot getModuleRoot(String path) throws ARESModelException { for (IARESModuleRoot root : getModuleRoots()) { if (StringUtils.equals(root.getPath().toString(), path)) { return root; } } return null; } public IARESResource[] findResource(String fullyQualifiedName) throws ARESModelException { List<IARESResource> resources = new ArrayList<IARESResource>(); for (IARESResource res : getResources()) { if (res.getFullyQualifiedName().equals(fullyQualifiedName)) { resources.add(res); } } return resources.toArray(new IARESResource[0]); } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IARESProject#findResource(java.lang.String, java.lang.String) */ public IARESResource findResource(String name, String type) throws ARESModelException { if (name == null || type == null) return null; String pkgName = ""; String fileName = name; if (name.indexOf('.') != -1) { pkgName = StringUtils.substringBeforeLast(name, "."); fileName = StringUtils.substringAfterLast(name, "."); } for (IARESModuleRoot root : getModuleRoots()) { IARESModule module = root.getModule(pkgName); if (module.exists()) { IARESResource res = module.getARESResource(fileName, type); if (res != null && res.exists()) { return res; } } } return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.core.IARESBundle#getRequiredBundles() */ @Override public IARESBundle[] getRequiredBundles() { return null; } /* (non-Javadoc) * @see com.hundsun.ares.studio.internal.core.ARESElement#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (!(o instanceof ReferencedLibrary)) { return false; } ReferencedLibrary other = (ReferencedLibrary) o; return super.equals(o) && this.getPath().equals(other.getPath()); } @Override public int hashCode() { // �ڲ����ⲿ�ļ�����������������Ҫ��·��������hashcode return Util.combineHashCodes(getPath().hashCode(), parent.hashCode()); } }