Ignorar arquivos temporários ao implementar serviço de notificação da API NIO 2.0

3 respostas
filipebezerra

Ola grandes mentes brilhantes e mestres da boa programação. Estou com um problema que tentei resolver aplicando meus conhecimentos mas não consegui resolver.

O meu ambiente de desenvolvimento
Windows 7 x64, Eclipse Juno 4.2, Java SE 7 update 9, API NIO 2.0.

O ambiente de testes
Windows XP SP3, Java 7 update 6.

Objetivo do sistema
Estou implementando um serviço de monitoramento e notificação de eventos que ocorrem em um dado diretório. O único evento tratado pela aplicação é de Criação/Edição de arquivos dentro do diretório configurado para o serviço.

Estou implementando a aplicação utilizando a interface WatchService. Nesta classe existe uma lógica para monitorar e notificar todo tipo de arquivo que seja criado na pasta.
Dentro os arquivos suportados, estão arquivos “.docx” criados pelo word, “.pdf”, “.rtf” criados pelo wordpad, “.txt” criados pelon notepad e qualquer outro tipo de arquivo.

O problema
O serviço notifica qualquer arquivo, de qualquer extensão, ou seja, arquivos temporários e os arquivos “fantasmas” ele também identifica. O meu problema é ignorar estes arquivos pelo meu serviço.

O código do serviço implementado abaixo, é somente o método que processo eventos:

for (;;) {
			WatchKey key = null;

			try {
				key = watcher.take();
			} catch (InterruptedException exception) {
				exception.printStackTrace();
				return;
			}

			if (isRecognizedPath(key) == false) {
				System.err.println("WatchKey não reconhecida!!");
				continue;
			}

			Path workingPath = keys.get(key);

			for (WatchEvent<?> event : key.pollEvents()) {
				Kind<?> kind = event.kind();

				// Um tipo de evento especial que provavelmente foi perdido ou
				// descartado
				if (kind == OVERFLOW) {
					continue;
				}

				WatchEvent<Path> processedEvent = cast(event);
				Path fileName = processedEvent.context();
				Path filePath = workingPath.resolve(fileName);

				try {
					LOGGER.info(
							String.format(
									"%s >> exists=%s; directory=%s; hidden=%s; regular=%s; temporary=%s; empty=%s.",
									filePath, Files.exists(filePath),
									Files.isDirectory(filePath),
									Files.isHidden(filePath),
									Files.isRegularFile(filePath),
									FileUtilities.isTemporaryFile(filePath),
									Files.size(filePath) == 0));
					System.out.println();
				} catch (IOException e) {
					LOGGER.severe(e.getClass().toString() + "; "
							+ e.getMessage());
				}

				if (isValidPath(filePath) == false) {
					continue;
				}

				eventNotifierWindow.setTxtNotificationText(filePath);
				eventNotifierWindow.setVisible(true);

				if (eventNotifierWindow.getWindowExitCode() == EXIT_CODE.CONFIRMED) {
					SendProtocolUI sendProtocolWindow = new SendProtocolUI();
					sendProtocolWindow.setAttachedField(filePath.toString());
					sendProtocolWindow.setVisible(true);

					if (sendProtocolWindow.isSentProtocol()) {
						try {
							FileUtilities.copyFile(filePath.toFile(),
									sendProtocolWindow
									.getTextProtocolNumber().getText());
						} catch (IOException e) {
							LOGGER.severe("Attempting move a sent protocol. Error: "
									+ e.getClass().getName()
									+ ": "
									+ e.getMessage());
							JOptionPane
							.showMessageDialog(
									eventNotifierWindow,
									"Falha ao tentar COPIAR o protocolo enviado para a pasta '"
											+ SystemUtilitiesConstants.DIR_NAME_PROTOCOLS_SENT
											+ "'.",
											"Falha ao mover arquivo",
											JOptionPane.ERROR_MESSAGE);
						}

						JOptionPane.showMessageDialog(eventNotifierWindow,
								"Protocolo enviado com sucesso!!!",
								"Envio de Protocolo",
								JOptionPane.INFORMATION_MESSAGE);
					}
				} else {
					try {
						FileUtilities.copyFile(filePath.toFile(), null);
					} catch (IOException e) {
						LOGGER.severe("Attempting move a not sent protocol. Error: "
								+ e.getClass().getName()
								+ ": "
								+ e.getMessage());
						JOptionPane
						.showMessageDialog(
								eventNotifierWindow,
								"Falha ao tentar copiar o arquivo não enviado para a pasta '"
										+ SystemUtilitiesConstants.DIR_NAME_PROTOCOLS_NOT_SENT
										+ "'.",
										"Falha ao copiar arquivo",
										JOptionPane.ERROR_MESSAGE);
					}
				}
			}

			// Reseta o token e remove do conjunto se o diretório estiver
			// inacessível
			if (resetKey(key) == false) {
				break;
			}
		}

A implementação deste método

if (isValidPath(filePath) == false) {
					continue;
				}

está descrita abaixo:

/**
	 * Valida o arquivo processado pelo evento detectado na pasta que está sendo
	 * monitorada. A validação inclui verificações como:<br>
	 * <b>Se o arquivo existir;<br>
	 * Se o arquivo não for um diretório;<br>
	 * Se o arquivo não estiver oculto (Uma exceção poderá ser lançada caso o
	 * arquivo esteja inacessível);<br>
	 * Se o arquivo é regular;<br>
	 * Se o arquivo não é temporário.<br>
	 * Se o arquivo contém conteúdo, ou seja, se seu tamanho em bytes é maior
	 * que 0</b>.
	 * 
	 * @param path
	 *            o caminho absoluto do arquivo processado pelo evento.
	 * @return <b>true</b> se o arquivo processado pelo evento é valido.
	 */
	public boolean isValidPath(Path path) {
		boolean exists = Files.exists(path);
		if (exists == false)
			return false;
		boolean directory = Files.isDirectory(path);
		if (directory)
			return false;
		boolean hidden;
		try {
			hidden = Files.isHidden(path);
		} catch (IOException exception) {
			// impossível acessar arquivo ou ler atributos
			return false;
		}
		long size;
		try {
			size = Files.size(path);
		} catch (IOException e) {
			// impossível acessar ou ler arquivo
			return false;
		}

		return hidden == false && Files.isRegularFile(path)
				&& FileUtilities.isTemporaryFile(path) == false && size > 0;
	}

[b]Por favor, alguém poderia fazer a imensa gentileza de me indicar uma solução, alguma dica valiosa que foi testada e funcionaria ou citar alguém que teve um problema parecido com o meu e conseguiu resolver?

Este serviço está em uma aplicação de sincronização de arquivos e é de imensa urgência, pois o prazo de entrega já expirou.[/b]

Deste antemão deixo meu agradecimento, ao pessoal do fórum a seus leitores. É um fórum admirável.

3 Respostas

filipebezerra

Poxa, obrigado heim pessoal do forum e administradores, ninguém nem para falar que não sabem como resolver ou que não entenderam.

Caramba eu pensei que neste forum o pessoal gostava de ser colaborativo e ajudar com a comunidade, é meu primeiro post e a primeira impressão é a que fica.

Muito obrigado aí pessoal por nenhuma ajuda.

E

Na sua lógica você não listou os arquivos que você queria ou os arquivos que você não queria.

Do jeito que você escreveu, vem tudo mesmo.

Como a aplicação que escreve os arquivos temporários não tem a obrigação de botar um flag “temporário” no arquivo (esse flag existe no Windows, mas nunca vi ninguém usando isso em uma aplicação de verdade) então o pessoal da Oracle não implementou, no NIO, uma verificação de “flag temporário” na API.

Como eu sempre digo: se a API não tem um filtro de arquivos (você deve ter lido a documentação com atenção, não?) então você tem de escrevê-lo você mesmo.

E

A propósito, estou desconfiado que você tinha de entregar o tal serviço às 18:00 de sexta-feira passada, e se cadastrou aqui no fórum às 17:00 - e casualmente era feriado na cidade de São Paulo - onde 80% dos integrantes do GUJ que respondem frequentemente trabalham ou estudam. Então você teve o azar de ninguém ver seu problema nesse dia.

Mesmo que não fosse feriado, é meio complicado alguém responder a você no final de uma tarde de sexta-feira, que é o dia nacional da cerveja :slight_smile:

Criado 25 de janeiro de 2013
Ultima resposta 31 de jan. de 2013
Respostas 3
Participantes 2