blob: da58eee75cb5d2754c09930fd9bc1f50022b93f5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.ivy.plugins.repository.vfs;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileType;
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.plugins.resolver.VfsResolver;
import org.apache.ivy.util.Message;
/**
* VFS implementation of the Resource interface
*/
public class VfsResource implements Resource {
private String vfsURI;
private FileSystemManager fsManager;
private transient boolean init = false;
private transient boolean exists;
private transient long lastModified;
private transient long contentLength;
private transient FileContent content = null;
private transient FileObject resourceImpl;
// Constructor
public VfsResource(String vfsURI, FileSystemManager fsManager) {
this.vfsURI = vfsURI;
this.fsManager = fsManager;
this.init = false;
}
private void init() {
if (!init) {
try {
resourceImpl = fsManager.resolveFile(vfsURI);
content = resourceImpl.getContent();
exists = resourceImpl.exists();
lastModified = content.getLastModifiedTime();
contentLength = content.getSize();
} catch (FileSystemException e) {
Message.debug(e);
Message.verbose(e.getLocalizedMessage());
exists = false;
lastModified = 0;
contentLength = 0;
}
init = true;
}
}
/**
* Get a list of direct descendants of the given resource. Note that attempts to get a list of
* children does <em>not</em> result in an error. Instead an error message is
* logged and an empty ArrayList returned.
*
* @return A <code>ArrayList</code> of VFSResources
*/
public List<String> getChildren() {
init();
List<String> list = new ArrayList<>();
try {
if (resourceImpl != null && resourceImpl.exists()
&& resourceImpl.getType() == FileType.FOLDER) {
for (FileObject child : resourceImpl.getChildren()) {
list.add(normalize(child.getName().getURI()));
}
}
} catch (IOException e) {
Message.debug(e);
Message.verbose(e.getLocalizedMessage());
}
return list;
}
public FileContent getContent() {
init();
return content;
}
/**
* Get the name of the resource.
*
* @return a <code>String</code> representing the Resource URL.
*/
public String getName() {
return normalize(vfsURI);
}
public Resource clone(String cloneName) {
return new VfsResource(cloneName, fsManager);
}
/**
* The VFS FileName getURI method seems to have a bug in it where file: URIs will have 4 forward
* slashes instead of 3.
*
* @param vfsURI ditto
* @return a normalized String representing the VFS URI
*/
public static String normalize(String vfsURI) {
if (vfsURI == null) {
return "";
}
if (vfsURI.startsWith("file:////")) {
vfsURI = vfsURI.replaceFirst("////", "///");
}
return vfsURI;
}
/**
* Get the last modification time of the resource.
*
* @return a <code>long</code> indicating last modified time.
*/
public long getLastModified() {
init();
return lastModified;
}
/**
* Get the size of the resource
*
* @return a <code>long</code> representing the size of the resource (in bytes).
*/
public long getContentLength() {
init();
return contentLength;
}
/**
* Flag indicating whether a resource is available for querying
*
* @return <code>true</code> if the resource is available for querying, <code>false</code>
* otherwise.
*/
public boolean exists() {
init();
return exists;
}
/**
* Return a flag indicating whether a provided VFS resource physically exists
*
* @return <code>true</code> if the resource physically exists, <code>false</code> otherwise.
*/
public boolean physicallyExists() {
// TODO: there is no need for this method anymore, replace it by calling exists();
init();
try {
return resourceImpl.exists();
// originally I only checked for a FileSystemException. I expanded it to
// include all exceptions when I found it would throw a NPE exception when the query was
// run on ill-formed VFS URI.
} catch (Exception e) {
Message.verbose("Fail to check the existence of the resource " + getName(), e);
return false;
}
}
public String toString() {
return VfsResolver.prepareForDisplay(getName());
}
public boolean isLocal() {
return getName().startsWith("file:");
}
public InputStream openStream() throws IOException {
return getContent().getInputStream();
}
}