| /* |
| * 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 |
| * |
| * http://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.netbeans.modules.masterfs; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.concurrent.atomic.AtomicReference; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import org.netbeans.modules.masterfs.providers.BaseAnnotationProvider; |
| import org.netbeans.modules.masterfs.providers.InterceptionListener; |
| import org.netbeans.modules.masterfs.providers.ProvidedExtensions; |
| import org.netbeans.modules.masterfs.providers.ProvidedExtensions.IOHandler; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.FileSystem; |
| |
| /** |
| * |
| * @author Radek Matous |
| */ |
| public class ProvidedExtensionsProxy extends ProvidedExtensions { |
| private Collection<BaseAnnotationProvider> annotationProviders; |
| private static ThreadLocal<Boolean> reentrantCheck = new ThreadLocal<>(); |
| |
| /** Creates a new instance of ProvidedExtensionsProxy */ |
| public ProvidedExtensionsProxy(Collection/*AnnotationProvider*/ annotationProviders) { |
| this.annotationProviders = annotationProviders; |
| } |
| |
| @Override |
| public IOHandler getCopyHandler(File from, File to) { |
| if (to == null) { |
| return null; |
| } |
| IOHandler retValue = null; |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext() && retValue == null;) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| ProvidedExtensions.IOHandler delgate = ((ProvidedExtensions)iListener).getCopyHandler(from, to); |
| retValue = delgate != null ? new DelegatingIOHandler(delgate) : null; |
| } |
| } |
| return retValue; |
| } |
| |
| public ProvidedExtensions.DeleteHandler getDeleteHandler(final File f) { |
| ProvidedExtensions.DeleteHandler retValue = null; |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext() && retValue == null;) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| ProvidedExtensions.DeleteHandler delegate = ((ProvidedExtensions)iListener).getDeleteHandler(f); |
| retValue = delegate != null ? new DelegatingDeleteHandler(delegate) : null; |
| } |
| } |
| return retValue; |
| } |
| |
| public ProvidedExtensions.IOHandler getRenameHandler(final File from, final String newName) { |
| final File to = new File(from.getParentFile(), newName); |
| IOHandler retValue = null; |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext() && retValue == null;) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| ProvidedExtensions.IOHandler delgate = ((ProvidedExtensions)iListener).getRenameHandler(from, newName); |
| retValue = delgate != null ? new DelegatingIOHandler(delgate) : null; |
| } |
| } |
| return retValue; |
| } |
| |
| public ProvidedExtensions.IOHandler getMoveHandler(final File from, final File to) { |
| if (to == null) { |
| return null; |
| } |
| IOHandler retValue = null; |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext() && retValue == null;) { |
| BaseAnnotationProvider provider = it.next(); |
| InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| ProvidedExtensions.IOHandler delgate = ((ProvidedExtensions)iListener).getMoveHandler(from, to); |
| retValue = delgate != null ? new DelegatingIOHandler(delgate) : null; |
| } |
| } |
| return retValue; |
| } |
| |
| public void createFailure(final FileObject parent, final String name, final boolean isFolder) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener != null) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| iListener.createFailure(parent, name, isFolder); |
| } |
| }); |
| } |
| } |
| } |
| |
| public void beforeCreate(final FileObject parent, final String name, final boolean isFolder) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener != null) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| iListener.beforeCreate(parent, name, isFolder); |
| } |
| }); |
| } |
| } |
| } |
| |
| public void deleteSuccess(final FileObject fo) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener != null) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| iListener.deleteSuccess(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| public void deleteFailure(final FileObject fo) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener != null) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| iListener.deleteFailure(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| public void createSuccess(final FileObject fo) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener != null) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| iListener.createSuccess(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| public void beforeDelete(final FileObject fo) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener != null) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| iListener.beforeDelete(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| public boolean canWrite(final File f) { |
| final Boolean ret[] = new Boolean [] { null }; |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ProvidedExtensions extension = (ProvidedExtensions)iListener; |
| if(ProvidedExtensionsAccessor.IMPL != null && |
| ProvidedExtensionsAccessor.IMPL.providesCanWrite(extension)) |
| { |
| ret[0] = ((ProvidedExtensions)iListener).canWrite(f); |
| } |
| } |
| }); |
| if(ret[0] != null && ret[0]) { |
| break; |
| } |
| } |
| } |
| return ret[0] != null ? ret[0] : super.canWrite(f); |
| } |
| |
| |
| public void beforeChange(final FileObject f) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).beforeChange(f); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void fileLocked(final FileObject fo) throws IOException { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new FileSystem.AtomicAction() { |
| @Override |
| public void run() throws IOException { |
| ((ProvidedExtensions) iListener).fileLocked(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| public void fileUnlocked(final FileObject fo) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).fileUnlocked(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public Object getAttribute(final File file, final String attrName) { |
| final AtomicReference<Object> value = new AtomicReference<>(); |
| for (BaseAnnotationProvider provider : annotationProviders) { |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| value.set(((ProvidedExtensions) iListener).getAttribute(file, attrName)); |
| } |
| }); |
| } |
| if (value.get() != null) { |
| return value.get(); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public long refreshRecursively(File dir, long lastTimeStamp, List<? super File> children) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| ProvidedExtensions pe = (ProvidedExtensions)iListener; |
| int prev = children.size(); |
| long ret = pe.refreshRecursively(dir, lastTimeStamp, children); |
| assert ret != -1 || prev == children.size() : "When returning -1 from refreshRecursively, you cannot modify children: " + pe; |
| if (ret != -1) { |
| return ret; |
| } |
| } |
| } |
| final File[] arr = dir.listFiles(); |
| if (arr != null) { |
| children.addAll(Arrays.asList(arr)); |
| } |
| return 0; |
| } |
| |
| @Override |
| public void createdExternally(final FileObject fo) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).createdExternally(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void deletedExternally(final FileObject fo) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).deletedExternally(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void fileChanged(final FileObject fo) { |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).fileChanged(fo); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void beforeMove(final FileObject from, final File to) { |
| if (to == null) { |
| return; |
| } |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).beforeMove(from, to); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void moveSuccess(final FileObject from, final File to) { |
| if (to == null) { |
| return; |
| } |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).moveSuccess(from, to); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void moveFailure(final FileObject from, final File to) { |
| if (to == null) { |
| return; |
| } |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).moveFailure(from, to); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void beforeCopy(final FileObject from, final File to) { |
| if (to == null) { |
| return; |
| } |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).beforeCopy(from, to); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void copySuccess(final FileObject from, final File to) { |
| if (to == null) { |
| return; |
| } |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).copySuccess(from, to); |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public void copyFailure(final FileObject from, final File to) { |
| if (to == null) { |
| return; |
| } |
| for (Iterator<BaseAnnotationProvider> it = annotationProviders.iterator(); it.hasNext();) { |
| BaseAnnotationProvider provider = it.next(); |
| final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null; |
| if (iListener instanceof ProvidedExtensions) { |
| runCheckCode(new Runnable() { |
| public void run() { |
| ((ProvidedExtensions)iListener).copyFailure(from, to); |
| } |
| }); |
| } |
| } |
| } |
| |
| public static void checkReentrancy() { |
| if (reentrantCheck.get() != null) { |
| Logger.getLogger("org.netbeans.modules.masterfs.ProvidedExtensionsProxy").log(Level.INFO,"Unexpected reentrant call", new Throwable());//NOI18N |
| |
| } |
| } |
| |
| private static void runCheckCode(Runnable code) { |
| try { |
| reentrantCheck.set(Boolean.TRUE); |
| code.run(); |
| } finally { |
| reentrantCheck.set(null); |
| } |
| } |
| private static void runCheckCode(FileSystem.AtomicAction code) throws IOException { |
| try { |
| reentrantCheck.set(Boolean.TRUE); |
| code.run(); |
| } finally { |
| reentrantCheck.set(null); |
| } |
| } |
| |
| private class DelegatingDeleteHandler implements ProvidedExtensions.DeleteHandler { |
| private ProvidedExtensions.DeleteHandler delegate; |
| private DelegatingDeleteHandler(final ProvidedExtensions.DeleteHandler delegate) { |
| this.delegate = delegate; |
| } |
| public boolean delete(final File file) { |
| final boolean[] retval = new boolean[1]; |
| runCheckCode(new Runnable() { |
| public void run() { |
| retval[0] = delegate.delete(file); |
| } |
| }); |
| return retval[0]; |
| } |
| } |
| |
| private class DelegatingIOHandler implements ProvidedExtensions.IOHandler { |
| private ProvidedExtensions.IOHandler delegate; |
| private DelegatingIOHandler(final ProvidedExtensions.IOHandler delegate) { |
| this.delegate = delegate; |
| } |
| public void handle() throws IOException { |
| final IOException[] retval = new IOException[1]; |
| runCheckCode(new Runnable() { |
| public void run() { |
| try { |
| delegate.handle(); |
| } catch (IOException ex) { |
| retval[0] = ex; |
| } |
| } |
| }); |
| if (retval[0] != null) { |
| throw retval[0]; |
| } |
| } |
| } |
| } |